Read, write, file formats¶
Overview¶
A ChemicalSystem can be created from, and saved to, many file formats commonly used
in computational chemistry (see Supported formats).
These are coordinate-based formats: each file stores a list of atoms with their positions, and, depending on the format, extra data such as the lattice, bonds, charges and atomic attributes. Most are plain text; the exception is the binary kf/rkf format.
Most formats cannot capture everything a ChemicalSystem holds, so reading or writing may lose information (e.g. .xyz files carry no bonds). Only the AMS-native in and kf / rkf formats are lossless.
Read/write to file¶
The two main entry points are from_file() and
write_file(), which deduce the format from the file extension
(or from an explicit format argument):
from scm.base import ChemicalSystem, Lattice
# Creating some systems for testing
water = ChemicalSystem.from_smiles("O")
periodic_water = water.copy()
periodic_water.lattice = Lattice.from_lattice_parameters(5,5,5) # 5 Å cubic cell
# Writing to file
# ===============
# File format deduced from the file extension (".xyz" in this case)
water.write_file("water.xyz")
# Optionally you can explicitly specify the file format.
# This takes precedence over the file extension.
periodic_water.write_file("periodic_water", format="cif")
# There are also dedicated methods to read/write in specific formats,
# some of which might take format-specific options, e.g.:
water.write_kf("ams.rkf", section="Molecule")
periodic_water.write_ase_xyz("periodic_water.xyz")
# Reading from file
# =================
# from_file is a constructor: it returns a NEW ChemicalSystem.
# File format deduced from the file extension
water_from_disk = ChemicalSystem.from_file("water.xyz")
print(water_from_disk)
# Optionally you can explicitly specify the file format.
periodic_water_from_disk = ChemicalSystem.from_file("periodic_water", format="cif")
# In case of failure to read/write, an exception will be raised.
try:
water.write_file("water", format="cif") # writing a non-periodic system to CIF fails
except Exception as e:
print(e)
Read/write to strings¶
Because most formats are plain text, you can also read from or write to an in-memory string, using from_string() and Python’s format:
from scm.base import ChemicalSystem
# Reading from strings
# ====================
xyz_string = """3
O 0.0 0.0 -0.3772
H 0.0 0.8002 0.1886
H 0.0 -0.8002 0.1886
"""
# The from_string method needs the format to be explicitly defined
water = ChemicalSystem.from_string(xyz_string, format="xyz")
# Printing / writing to strings
# =============================
# When converting the chemical system to string, the default format is "in"
print(water)
# ...but you can use Python f-string formatting to specify the file format:
print(f"{water:xyz}")
print(f"{water:mol}")
# Equivalently, you can use the format method:
pdb_string = format(water, "pdb")
print(pdb_string)
Line notation (SMILES)¶
A ChemicalSystem can also be created from a line notation such as SMILES, and a system
that has bonds can be written back out as SMILES with to_smiles().
Note that, unlike other formats described on this page, SMILES encodes only the connectivity (the molecular graph) and no coordinates, so a 3D geometry is generated when it is read. See SMILES.
from scm.base import ChemicalSystem
benzene = ChemicalSystem.from_smiles("c1ccccc1")
print(benzene)
# Note: the xyz format does not include bonds.
water = ChemicalSystem.from_file("water.xyz") # assumes water.xyz from the example above
# When converting to a SMILES string, the bonds in the chemical system
# will be used for the connectivity. You can use the guess_bonds() method
# if the chemical system does not already have bonds
water.guess_bonds()
print(water.to_smiles())
Supported formats¶
These are the supported coordinate-based formats (all can be both read and written). The check marks show which extra information, besides the atomic coordinates, each format is able to store:
Format |
Bonds |
Periodic |
Total Charge |
Atomic attributes |
Description |
Encoding |
|---|---|---|---|---|---|---|
✓ |
Any |
✓ |
✓ |
AMS-native System block. Lossless. |
text |
|
✓ |
Any |
✓ |
✓ |
AMS-native binary file. Lossless. |
binary |
|
Any |
✓ |
✓ |
XYZ file. Extended AMS and ASE variants add extra info (see xyz). |
text |
||
✓ |
see notes |
Tripos MOL2. Atomic attributes: only forcefield atom types and charges. |
text |
|||
✓ |
Protein Data Bank. Often omits hydrogen atoms. |
text |
||||
✓ |
MDL Molfile. |
text |
||||
3D only |
Crystallographic Information File. Symmetry is expanded on read; writing produces a P1 cell. |
text |
||||
3D only |
VASP POSCAR / CONTCAR. The files are conventionally extensionless. |
text |
||||
Any |
DMol3 file. |
text |
API¶
Besides the generic from_file() / write_file() interface, every
supported format has dedicated from_* and write_* methods. Use these when you want to be explicit about the
format, or when you need a format-specific option (such as the KF section name).
Generic from/to file¶
The generic methods from_file() and write_file() deduce
the file format from the file extension.
Pass the optional format argument to override that, or when the file has no usable extension.
- classmethod ChemicalSystem.from_file(filename: str, format: str = '') ChemicalSystem
Constructs and returns a new ChemicalSystem from a file.
The file format is deduced from the extension of
filenameunless it is given explicitly through theformatargument. The supported format identifiers are:kf/rkf(binary KF files),in(AMS System blocks),xyz(extended XYZ files),mol2(MOL2 files),pdb(PDB files),mol(MDL MOL files),cif(Crystallographic Information Files),poscar(VASP POSCAR/CONTCAR files) anddmol(DMol3 files). POSCAR files are additionally auto-detected from a.vaspor.contcarextension, or aPOSCAR/CONTCARfilename.- Parameters:
filename – Path to the file to read.
format – File format, e.g.
"xyz". If empty, it is deduced from the filename extension.
- Returns:
A new ChemicalSystem read from the file.
Note this may raise a ChemicalSystemError if the format cannot be deduced or is not supported, or if the file does not exist or cannot be parsed.
- ChemicalSystem.write_file(filename: str, format: str = '') None
Writes the ChemicalSystem to a file.
This is the complement of
from_file(): the format is deduced from the extension offilenameunless given explicitly throughformat. The same formats are supported as for reading, with the caveat thatcifandposcarrequire a 3D lattice, andpdb/molare written via RDKit.- Parameters:
filename – Path to the file to write.
format – File format, e.g.
"xyz". If empty, it is deduced from the filename extension.
Note this may raise a ChemicalSystemError if the format cannot be deduced or is not supported, or if the system cannot be written in the requested format.
Generic from/to strings¶
A ChemicalSystem can be converted to a string and parsed back from one, without going through a file.
- classmethod ChemicalSystem.from_string(content: str, format: str) ChemicalSystem
Constructs and returns a new ChemicalSystem from an in-memory string.
This is the in-memory counterpart of
from_file(). Unlikefrom_file(), theformatis required, as there is no filename to deduce it from. The same text formats are supported as forfrom_file()(in,xyz,mol2,pdb,mol,cif,poscaranddmol); the binarykf/rkfformat is not supported and raises.- Parameters:
content – The file contents to parse.
format – File format, e.g.
"xyz".
- Returns:
A new ChemicalSystem parsed from the string.
Note this may raise a ChemicalSystemError if the format is missing, unsupported (e.g.
kf), or if the content cannot be parsed.
- ChemicalSystem.__format__(format_spec: str) str
Formats a ChemicalSystem into a string representation.
The
format_specstring starts with and identifier for the format to write, followed and optional:and a list of space separatedkey=valuepairs configuring options of the format. E.g. the following would produce the AMS System block format in internal units (bohr) with the string “H2O” as a System name in the block header:cs = ChemicalSystem(...) print(f"{cs:in:units=internal name=H2O}")
Would produce the output:
System H2O Atoms [bohr] O 0 0 -0.7262847342654172 H 0 1.4669943905469853 0.3631423765813393 H 0 -1.4669943905469853 0.3631423765813393 End End
The following formats and options are supported at the moment:
infor writing the AMS System block. This is the default format, if none is specified. The following options are supported:name=...to put an arbitrary string as the system’s name into the block header.units=[default|internal]to switch between default units and the units used by the ChemicalSystem internally. Internally the ChemicalSystem uses atomic units (e.g. bohr for lengths). Printing the System block in internal units avoids a possible loss in precision in the unit conversion and guarantees an exactChemicalSystem -> str -> ChemicalSystemround-trip, i.e.:cs = ChemicalSystem(...) assert ChemicalSystem(f"{cs:in:units=internal}") == cs
skip=[gui|adf|band|forcefield|dftb|reaxff|qe|...]to avoid printing of a particular property group in the end-of-line string of an atom in the System%Atoms subblock. Multiple groups may be specified as a comma separated list.unused_atom_attributes=[drop|include]to determine whether unused atomic attributes groups should be written out asModify%EnableAtomAttributesentries. The default is not to do this, akadrop. This means that unused atomic attributes groups get lost in theChemicalSystem -> str -> ChemicalSystemround-trip. If preserving them is important, this can be achieved by setting this option toinclude.
xyzfor writing a plain XYZ file without lattice or atomic attributes. This format has no options.extended_xyzfor writing the AMS extended XYZ format. This format has no options.ase_xyzfor writing the ASE-style extended XYZ format (lattice on the comment line asLattice="..."). This format has no options.mol2,cif,poscar,dmol,pdbandmolfor the corresponding file formats (the same ones supported byfrom_file()/write_file()). These have no options.cifandposcarrequire a 3D lattice;pdbandmolare produced via RDKit.outfor a human-readable summary of the system (as printed to standard output by AMS). No options.asefor formatting using ASE. Examples:print(f"{cs:ase:extxyz}")for the ASE extended XYZ format, orprint(f"{cs:ase:vasp}")for the POSCAR format. The full list of allowed formats can be obtained by running the commandamspython -m ase info --formats.
SMILES¶
A ChemicalSystem can be created from a SMILES string, generating a reasonable 3D geometry, and conversely a canonical SMILES string can be derived from an existing ChemicalSystem’s bonds and geometry:
- classmethod ChemicalSystem.from_smiles(smiles: str, optimize_with_uff: bool = True, num_trial_conformers: int = 10) ChemicalSystem
Converts a SMILES string to a ChemicalSystem.
To generate a reasonable starting configuration, by default multiple trial conformers will be generated and optimized with UFF. The lowest energy of these conformers is then selected. This behaviour can be altered by setting
optimize_with_uff=False, or modifyingnum_trial_conformers. Disconnected molecules (separated by.) are arranged non-overlapping in space. Note this may raise a ChemicalSystemError if the conversion cannot be completed.
- ChemicalSystem.to_smiles() str
Converts a ChemicalSystem to a canonical SMILES string, derived from its bonds and geometry.
The SMILES is built from the system’s bonds, so the ChemicalSystem must contain bonding information for the result to be meaningful. If the bonds are not already defined, call
guess_bonds()first to perceive them from the geometry.Note this does not take into account any atomic charges, and may raise a ChemicalSystemError if the conversion cannot be completed.
in (System block)¶
The System block is an AMS-native, lossless, human-readable text format that describes the full chemical system, including bonds, lattice, charges and atomic attributes. For the full syntax and options, see the AMS System Block documentation. Example of an in file (System block) for a water molecule:
System
Atoms
O 0.0 0.0 -0.404121
H 0.0 0.783036 0.202060
H 0.0 -0.783036 0.202060
End
BondOrders
1 2 1
1 3 1
End
End
- classmethod ChemicalSystem.from_in(filename: str, name: str = '') ChemicalSystem
Constructs and returns a new ChemicalSystem from a (possibly named) System block in an AMS input file.
kf / rkf¶
The AMS binary kf file is lossless and can hold several systems in different
sections, so both methods take a section argument (default "Molecule").
- classmethod ChemicalSystem.from_kf(filename: str, section: str = 'Molecule') ChemicalSystem
- classmethod ChemicalSystem.from_kf(kf: KFFile, section: str = 'Molecule') ChemicalSystem
Constructs and returns a new ChemicalSystem from a section on a KF file.
xyz¶
The XYZ format is a simple text format storing element symbols and Cartesian coordinates, but no bonds. AMS handles three variants:
plain XYZ: coordinates only, no periodicity. Example for a water molecule:
3
O 0.0 0.0 -0.404121
H 0.0 0.783036 0.202060
H 0.0 -0.783036 0.202060
AMS-extended XYZ: additionally stores the lattice, total charge and atomic attributes (see the AMS-extended XYZ documentation). Example for diamond:
2
C -0.44625 -0.44625 -0.44625
C 0.44625 0.44625 0.44625
VEC1 0.000 1.785 1.785
VEC2 1.785 0.000 1.785
VEC3 1.785 1.785 0.000
ASE-extended XYZ: the ASE convention, which stores the lattice on the comment line as Lattice="...".
Example for diamond:
2
Lattice="0 1.785 1.785 1.785 0 1.785 1.785 1.785 0" pbc="T T T" Properties=species:S:1:pos:R:3
C -0.44625 -0.44625 -0.44625
C 0.44625 0.44625 0.44625
Note: all three variants conventionally have the same .xyz extension.
from_xyz() reads all three automatically.
write_xyz() writes the AMS-extended variant by default; pass
extended_xyz_format=False for a plain XYZ file, or use write_ase_xyz()
for the ASE variant.
- classmethod ChemicalSystem.from_xyz(filename: str) ChemicalSystem
Constructs and returns a new ChemicalSystem from an extended XYZ file.
Lattice vectors may be given either in the AMS style, as
VEC1/VEC2/VEC3lines following the atoms, or in the ASE style, as aLattice="ax ay az bx by bz cx cy cz"entry on the comment line (the second line), optionally accompanied by apbc="px py pz"flag marking which directions are periodic. If both are present, theVEClines take precedence.
- ChemicalSystem.write_xyz(filename: str, extended_xyz_format: bool = True) None
Writes a ChemicalSystem to an XYZ file.
By default the file is written in the AMS extended XYZ file format, which includes lattice vectors, atomic attributes, regions and some system properties such as the total charge. In order to write a plain standard XYZ files without any of these extensions, set
extended_xyz_formattoFalse.
- ChemicalSystem.write_ase_xyz(filename: str) None
Writes a ChemicalSystem to an ASE-style extended XYZ file.
This is an alternative to
write_xyz(): instead of the AMSVEC1/VEC2/VEC3lines, the lattice is written on the comment line asLattice="ax ay az bx by bz cx cy cz"together with apbc="..."flag and an extended-XYZPropertiesfield, and each atom is written assymbol x y z. Such files can be read back withfrom_xyz()/from_file().
mol2¶
The MOL2 format is a text format that stores bonds, along with per-atom types and partial charges. Example of a .mol2 file for water:
# mol2 file for water
@<TRIPOS>MOLECULE
LIG
3 2 1 0 0
SMALL
@<TRIPOS>ATOM
1 O 0.0000 0.0000 -0.4041 O 0 LIG 0.000000
2 H 0.0000 0.7830 0.2021 H 0 LIG 0.000000
3 H 0.0000 -0.7830 0.2021 H 0 LIG 0.000000
@<TRIPOS>BOND
1 1 2 1
2 1 3 1
@<TRIPOS>SUBSTRUCTURE
1 LIG 1 TEMP 0 **** **** 0 ROOT
- classmethod ChemicalSystem.from_mol2(filename: str) ChemicalSystem
Constructs and returns a new ChemicalSystem from an extended MOL2 file.
pdb¶
PDB files are read and written using RDKit as backend. Note that PDB files often omit hydrogen atoms, so the resulting system may be missing hydrogens. Example of a .pdb file for water:
HETATM 1 O1 UNL 1 0.000 0.000 -0.404 1.00 0.00 O
HETATM 2 H1 UNL 1 0.000 0.783 0.202 1.00 0.00 H
HETATM 3 H2 UNL 1 0.000 -0.783 0.202 1.00 0.00 H
CONECT 1 2 3
END
- classmethod ChemicalSystem.from_pdb(filename: str) ChemicalSystem
Constructs and returns a new ChemicalSystem from a PDB file.
The file is parsed using RDKit as backend. All atoms are kept exactly as they appear in the file, including hydrogens, and no chemical sanitization is performed, so unusual or incomplete structures (common in PDB files) will not cause the read to fail. Bonds are taken from the file’s
CONECTrecords and, where those are absent, perceived from interatomic distances.- Parameters:
filename – Path to the PDB file to read.
- Returns:
A new ChemicalSystem holding the atoms, coordinates and bonds from the file.
Note this may raise a ChemicalSystemError if the file cannot be read or parsed.
mol¶
MDL MOL files are read and written using RDKit as backend, and include bonds. Example of a .mol file for water:
water
3 2 0 0 0 0 0 0 0 0999 V2000
0.0000 0.0000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
0.7570 0.5860 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.7570 0.5860 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0
1 3 1 0
M END
- classmethod ChemicalSystem.from_mol(filename: str) ChemicalSystem
Constructs and returns a new ChemicalSystem from an MDL MOL file.
The file is parsed using RDKit as backend. All atoms are kept exactly as they appear in the file, including hydrogens, and no chemical sanitization is performed, so unusual or incomplete structures will not cause the read to fail. Bonds and their bond orders are taken from the file’s bond block.
- Parameters:
filename – Path to the MOL file to read.
- Returns:
A new ChemicalSystem holding the atoms, coordinates and bonds from the file.
Note this may raise a ChemicalSystemError if the file cannot be read or parsed.
cif¶
The CIF format describes periodic (crystalline) systems. Reading expands the asymmetric unit into the full unit cell: using the file’s explicit symmetry operators if present, otherwise the operators of the space group looked up in spglib from the space-group number or Hermann-Mauguin symbol. A file with neither is read as the asymmetric unit only. Writing produces a P1 cell (no symmetry reduction) and requires a 3D lattice. Example of .cif for diamond:
data_diamond_cif_file
_symmetry_space_group_name_H-M 'P 1'
_symmetry_Int_Tables_number 1
_cell_length_a 2.5243712088
_cell_length_b 2.5243712088
_cell_length_c 2.5243712088
_cell_angle_alpha 60.0
_cell_angle_beta 60.0
_cell_angle_gamma 60.0
loop_
_symmetry_equiv_pos_as_xyz
'x, y, z'
loop_
_atom_site_label
_atom_site_type_symbol
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
C1 C -0.1250000000 -0.1250000000 -0.1250000000
C2 C 0.1250000000 0.1250000000 0.1250000000
- classmethod ChemicalSystem.from_cif(filename: str) ChemicalSystem
Constructs and returns a new ChemicalSystem from a CIF (Crystallographic Information File).
The cell parameters and the atoms of the asymmetric unit (given in fractional or Cartesian coordinates) are read. If the file lists explicit symmetry operations (
_symmetry_equiv_pos_as_xyzor_space_group_symop_operation_xyz), they are applied to expand the asymmetric unit into the full unit cell, with atoms on coinciding positions deduplicated. If the file has no explicit operator list but does identify a space group (through_symmetry_Int_Tables_numberor a Hermann-Mauguin symbol_symmetry_space_group_name_H-M), the operators are looked up in spglib’s space-group database and applied. When this lookup is needed and the file supplies both identifiers, they must admit a common Hall setting. Identifier inconsistencies are ignored when explicit operators are present, because those operators are authoritative. A structure with neither operators nor an identifiable space group is read as the asymmetric unit only.- Parameters:
filename – Path to the CIF file to read.
- Returns:
A new ChemicalSystem holding the (expanded) atoms and the unit cell.
Note this may raise a ChemicalSystemError if the file cannot be read or parsed.
- ChemicalSystem.write_cif(filename: str) None
Writes the ChemicalSystem to a CIF file.
A minimal P1 file is written (the cell, an explicit identity symmetry operation, and every atom in fractional coordinates); no symmetry reduction is attempted. Requires a 3D lattice, otherwise a ChemicalSystemError is raised.
poscar¶
POSCAR (and CONTCAR) files describe periodic systems for VASP. These files conventionally have no extension. Writing requires a 3D lattice. Example of a POSCAR file for diamond:
Diamond
1.0
0.0000000000000000 1.7849999999999999 1.7849999999999999
1.7849999999999999 0.0000000000000000 1.7849999999999999
1.7849999999999999 1.7849999999999999 0.0000000000000000
C
2
Direct
-0.1250000000000000 -0.1250000000000000 -0.1250000000000000
0.1250000000000000 0.1250000000000000 0.1250000000000000
- classmethod ChemicalSystem.from_poscar(filename: str) ChemicalSystem
Constructs and returns a new ChemicalSystem from a VASP POSCAR / CONTCAR file.
The unit cell, element symbols and atom positions (in direct/fractional or Cartesian coordinates) are read. The scale line may contain one universal factor (including the negative-value “target volume” convention) or three positive factors for the Cartesian x, y and z components. Both the VASP 5 format (with an explicit element-symbol line) and the legacy VASP 4 format (with the element symbols on the comment line) are supported. Any “Selective dynamics” flags are ignored.
- Parameters:
filename – Path to the POSCAR/CONTCAR file to read.
- Returns:
A new ChemicalSystem holding the atoms and the unit cell.
Note this may raise a ChemicalSystemError if the file cannot be read or parsed.
dmol¶
The DMol3 format is a simple text format storing Cartesian coordinates (in angstrom) and, for periodic systems, the cell vectors. It does not include bonds. Example of a .dmol file for diamond:
$cell_vectors
0.0000000000 1.7850000000 1.7850000000
1.7850000000 0.0000000000 1.7850000000
1.7850000000 1.7850000000 0.0000000000
$coordinates
C -0.4462500000 -0.4462500000 -0.4462500000
C 0.4462500000 0.4462500000 0.4462500000
$end
- classmethod ChemicalSystem.from_dmol(filename: str) ChemicalSystem
Constructs and returns a new ChemicalSystem from a DMol3 .dmol file.
The Cartesian atom coordinates and, if present, the cell vectors are read (both in angstrom).
- Parameters:
filename – Path to the .dmol file to read.
- Returns:
A new ChemicalSystem holding the atoms and (optionally) the unit cell.
Note this may raise a ChemicalSystemError if the file cannot be read or parsed.
ASE formats¶
A ChemicalSystem can also be created from any format supported by ASE via an intermediate ase.Atoms instance.
- classmethod ChemicalSystem.from_ase_read(filename: str | IO, index: Any | None = None, format: str | None = None, **kwargs) ChemicalSystem
Loads a ChemicalSystem from a file using
ase.io.read. See ASE documentation for details.Calling this method may throw an ImportError if the
asepackage can not be found in your Python environment.Note that the construction of the ChemicalSystem is via
ase.Atoms. SeeChemicalSystem.from_ase_atomsfor details and restrictions.