Reading and writing CIF files

httk-atomistic ships the CIF/mCIF parser, reader and writer stack under httk.atomistic.io.cif, and registers its readers with httk-core through httk.registry.io.atomistic. Importing httk.core therefore discovers the .cif loader, so httk.core.load can dispatch a CIF file. .cif, .mcif and their compressed forms (.cif.gz, .cif.bz2) all dispatch here.

Plain load(path) returns the native ASUStructure — a structure held as its asymmetric unit, expanding to a full cell on demand (see Structures and Asymmetric units). Pass raw=True to get the neutral parsed CIF payload instead, when you want the file’s contents without interpreting them as a structure:

import httk.core  # discovery registers the ".cif" loader

payload = httk.core.load("structure.cif", raw=True)
block = payload["blocks"][0]           # one neutral asymmetric-unit mapping per structural block
print(payload["header"])               # the file's leading comment lines
print(block["symbols"])                # e.g. ["Na", "Cl"]
print(block["cell_parameters_exact"])  # ("a", "b", "c", "alpha", "beta", "gamma") as verbatim tokens

The neutral CIF payload

The neutral payload is a mapping with format "cif" ("mcif" for magnetic CIFs), a blocks list holding one asymmetric-unit mapping per structural block, unparsed reasons for blocks that have atom sites but cannot be interpreted, and the verbatim header. Numeric values are kept as strings; where the file carries _httk_*_exact companion tags those exact tokens are preferred, so no precision is lost at the I/O layer.

Two conveniences smooth over real-world files:

  • Inferred element symbols. _atom_site_type_symbol is optional in the CIF core dictionary. When it is absent, each site’s element is inferred from the leading element run of its _atom_site_label ("MgM1"Mg), with a RuntimeWarning. A label whose prefix names no element is not guessed at: its block cannot be interpreted, so load omits it from blocks and records the reason in unparsed (the underlying parser raises a ValueError that the loader catches per block).

  • Autocorrect. Passing autocorrect=True to load (or to read_cif / read_cif_asus) drops a malformed auxiliary loop — one whose column counts do not line up and whose tags are not a protected structural family — warning about each repair instead of refusing the file, and stamps autocorrect=True on the payload. Without it, such a loop is a hard ValueError.

Lower-level API

The runnable Reading, inspecting and writing CIF files walks the lower-level read_cif, parse_cif_float / parse_cif_int and write_cif API in full. read_cif parses a CIF into a (data_blocks, header) tuple of raw named blocks without interpreting any tag’s meaning; read_cif_asus interprets the blocks into asymmetric-unit mappings; and write_cif reconstructs a CIF, including its loop_ sections, from that neutral form. read_cif and read_cif_asus are importable from httk.atomistic.io.cif; write_cif lives in httk.atomistic.io.cif.cif_writer and the parse helpers in httk.atomistic.io.cif.cif_parser.