Table of Contents
About
readcon-core is the reference implementation of versioned .con / .convel.
This stack puts CON everywhere: every optimizer, potential driver, analysis
tool, campaign store, and ML hand-off that needs a durable atomic configuration
with constraints, forces, and identity.
CON is human-readable and complete on one frame: cell, type-grouped
coordinates, per-direction fixed masks, column-5 atom_id, optional per-atom
sections (velocities, forces, energies, charges, spins, magmoms), and JSON
metadata (spec v2–v3, docs/orgmode/spec.org).
That payload is why saddle, dimer, and NEB codes already work on CON; the
library exists so the rest of the atomistic stack adopts the same file.
Already on that path: rare-event clients, rgpot, rgpycrumbs, ASE adapters, amsel, campaign stores, and anything that takes DLPack or metatensor blocks.
Rust rewrite of readCon. Chemfiles owns format diversity at the edge; this crate owns CON fidelity on the wire and in memory.
Measurements: Cachegrind I-refs (examples/cachegrind_harness.rs);
Python ASV + spyglass on PRs (benchmarks/); CON peers via
benches/compare_readers.py (and other scripts under benches/).
See docs/orgmode/benchmarks.org.
Features
- CON and convel: Coordinates; optional sections declared in
sections(velocities, forces, energies, charges, spins, magmoms). Velocities also auto-detect on legacy.convelwithout asectionskey. - Lazy iteration:
ConFrameIterator;next_with_raw_spankeeps the on-disk blob for corpus ingest. - Hot path: fast-float2, memmap2, Cachegrind-tracked scenarios.
- Parallel frames: Rayon behind the
parallelCargo feature. - Bindings: Python (PyO3), Julia (ccall), C (shipped header), C++ (RAII header), Fortran (fpm); hourglass ABI patterned on metatensor.
- Metadata helpers: Typed
energy,frame_index,time,timestep,neb_bead,neb_bandacross bindings; raw JSON still available. - Validation:
validate=trueenforces finiteness, reserved keys, geometry, labels, symbols, section presence, identity columns. - Fidelity:
atom_id, per-direction fixed masks, and declared optional sections round-trip through the core reader/writer. - Campaigns: Pair with readcon-db (CON-text indexes, dedup, multi-reader; docs · docs.rs).
- RPC: Cap'n Proto behind the
rpcfeature.
Migrate onto CON
Why switch: use a real frame API and multi-language library instead of hand-rolling XYZ and a private atoms object.
-
API: parse/write, builders, metadata, validation, compression, lazy multi-frame iteration
-
Payload: constraints,
atom_id, optional sections, versioned JSON on one frame -
Selection:
select_atoms/rkr_frame_select(name H, bonds/angles when topology is present) -
Languages: hourglass
rkr_*in Fortran / C / C++ / Python / Julia / Rust (same semantics when you add a language) -
Campaigns: readcon-db on CON text (energy / formula / sections, dedup, multi-reader; docs · docs.rs)
-
Plotting: chemparseplot (+ rgpycrumbs) on the same files
-
Measurements: Cachegrind I-refs; PR ASV + spyglass; peer scripts in
benches/— benchmarks.orgforeign → CON (needs --features chemfiles)
cargo run --release --features chemfiles -- convert structure.xyz structure.con
Python (readcon-chemfiles or maturin --features python,chemfiles)
python -c "import readcon; readcon.convert_to_con('structure.xyz','structure.con')"
How-to: docs/orgmode/migrate.org. Chemfiles path (CI-run): chemfiles-notebook. Campaigns: readcon-db docs · docs.rs/readcon-db. Plotting: chemparseplot.
Install
The C/C++ headers are shipped (include/readcon-core.h). cbindgen is a maintainer tool, not a consumer dependency. C99 (readcon-core.h) or C++17 (readcon-core.hpp) compiler. FetchContent URL: readcon-core-cxx-$VERSION.tar.gz on the GitHub Release.
Full matrix: getting-started.
Tutorial
One Good Tutorial (Diátaxis): install, read a multi-frame fixture, inspect
atom_id, write a round-trip, build a frame with energy. Full steps:
docs/orgmode/tutorial.org (or the published HTML tutorial page).
Short Python path from the repository root:
import readcon
for frame in readcon.iter_con("resources/test/tiny_multi_cuh2.con"):
print(frame.cell, len(frame), frame.energy)
frames = readcon.read_con("resources/test/tiny_multi_cuh2.con")
readcon.write_con("out.con", frames)
atoms = [readcon.Atom("Cu", 0.0, 0.0, 0.0, atom_id=0, mass=63.546)]
frame = readcon.ConFrame(cell=[10.0, 10.0, 10.0], angles=[90.0, 90.0, 90.0], atoms=atoms)
frame.set_energy(-42.5)
frame.write_con("built.con")
Rust smoke (same fixture):
cargo run --example rust_usage -- resources/test/tiny_multi_cuh2.con
Other languages and task recipes: docs/orgmode/howto.org. Conversion from XYZ/PDB/GRO: chemfiles-tutorial.
Design Decisions
- Lazy parsing:
ConFrameIteratorparses one frame at a time for large trajectories. - Hourglass FFI: shipped C header plus a hand-written C++ RAII wrapper, same pattern as metatensor. CMake FetchContent, Meson wrap, and
readcon-core.pcdo not run cbindgen.
FFI Layer
Two exposure modes:
- Opaque handles (
RKRConFrame*): client calls Rust accessors (rkr_frame_get_header_line, …). Hides layout; ABI can evolve behind the handle. - Transparent
#[repr(C)]extract (rkr_frame_to_c_frame→CFrame): client owns a flat atom table for hot loops and frees it withfree_c_frame.
Specification
See docs/orgmode/spec.org (or the published HTML build) for the full specification. A summary follows.
CON format
- A 9-line header (comments, cell dimensions, cell angles, atom type/count/mass metadata)
- Line 2 is reserved for spec-v2 JSON metadata
- Per-type coordinate blocks (symbol, label, atom lines with x y z fixed atomID)
- Optional spec-v2
sectionsandvalidatemetadata for declared per-atom sections and strict validation - Multiple frames are concatenated directly with no separator
convel format
Same as CON, with an additional velocity section after each frame's coordinates:
- A blank separator line
- Per-type velocity blocks (symbol, label, atom lines with vx vy vz fixed atomID)
Capabilities
Predecessor: readCon.
Citation
If you use readcon-core in academic work, please cite it via the metadata in CITATION.cff. The Zenodo DOI tracks the latest release.
License
MIT.