Design - QVF container format for visualization data¶
Status: QVF v1 is implemented, not just proposed. The canonical machine-readable contract is
python/vibeqc/output/formats/qvf_manifest.schema.json. This document is the human tech spec for that schema and for the current vibe-qc writer / vibe-view reader contract.
QVF (.qvf, “Quantum Visualization Format”) is a ZIP-based container
for quantum-chemistry visualization and analysis data. It is designed
to keep one calculation’s structure, scalar fields, spectra, bands,
trajectories, provenance, and viewer hints in one random-access file
instead of scattering them across Cube, XYZ, Molden, XSF, log, and
program-specific sidecar files.
The format is intended for the whole quantum-chemistry ecosystem, not
only vibe-qc. A QVF producer may be any quantum-chemistry code. A QVF
consumer may be a structure viewer, a band plotter, a spectrum tool, a
validator, a notebook script, or the reference GPU viewer vibe-view.
0. Changes Since The May 2026 Blog Post¶
The May 21, 2026 blog post “Quantum chemistry needs a modern file format” described the motivation and early direction. The implementation has moved since then:
Area |
Blog-era statement |
Current QVF v1 state |
|---|---|---|
Reference viewer |
A viewer was on the roadmap. |
|
Writer |
QVF writer was described as part of the output plan. |
|
Validator |
|
|
Wavefunctions |
Wavefunction coefficient matrices were originally scoped out. |
|
Provenance |
The blog used “provenance” broadly. |
|
Extensibility |
The blog sketched semver-by-kind. |
Closed in v1.1. Formal |
DOS/PDOS |
Not mentioned. |
New in v1.1: |
Electrostatic potential |
Not mentioned. |
New in v1.1: |
NCI / RDG surfaces |
Not mentioned. |
New in v1.1: |
Fermi surface |
Not mentioned. |
New in v1.1: |
Phonon bands + DOS |
Not mentioned. |
New in v1.1: |
Equation of state |
Not mentioned. |
New in v1.1: |
Metadata |
The blog used “provenance” broadly. |
New in v1.1: optional root metadata for |
This document is therefore both a specification and a correction point for the next public write-up: QVF is no longer only a proposal, but its extension governance should still be described honestly.
1. Design Goals¶
QVF v1 is built around six goals:
One shareable artifact. A calculation’s visualization data should travel as one
.qvffile.Random access. A consumer should read only the members it needs. A structure-only viewer should not load a 500 MB density grid.
Typed payloads. Every member has a declared format, dtype, shape, and checksum where applicable.
Stable common vocabulary. Common data types use canonical section kinds such as
structure,volume.density,bands, andspectra.ir.Partial support. A consumer can support a subset of kinds and still open the file. Unsupported vendor sections are reported rather than interpreted incorrectly.
Producer neutrality. The
source.programfield can name any code. The core section kinds are not vibe-qc-specific.
QVF v1 is deliberately not a restart format. It does not attempt to
encode integral caches, SCF internal state, grids used internally by a
particular DFT engine, or every possible wavefunction representation.
The optional wavefunction.gto section is a visualization-oriented
Molden-like molecular orbital carrier, not a universal restart record.
2. Archive Model¶
A QVF file is a ZIP archive. The only mandatory ZIP member is
manifest.json. Every other member is named from the manifest, so
member paths are part of the manifest contract rather than hard-coded
by the container itself.
A typical vibe-qc-produced archive looks like this:
example.qvf
├── manifest.json
├── structure/
│ ├── structure.json
│ └── symmetry.json
├── bonds/
│ └── connectivity.json
├── volumes/
│ ├── Electron_density.dat
│ ├── Electron_density_grid.json
│ ├── HOMO.dat
│ └── HOMO_grid.json
├── bands/
│ ├── kpath.json
│ └── eigenvalues.bin
├── spectra/
│ ├── ir.json
│ └── raman.json
├── trajectories/
│ ├── opt.json
│ └── opt_coords.bin
├── wavefunction/
│ ├── basis.json
│ ├── mo_metadata.json
│ └── mo_coefficients.bin
└── citations/
└── references.bib
The exact paths may differ. Consumers must follow the path fields in
manifest.json. Producers should use stable, readable directories for
debuggability, but path layout is not semantic.
There is no separate viewer_defaults.json; viewer hints live in the
root viewer_defaults object in manifest.json.
2.1 manifest.json¶
Minimal manifest shape:
{
"qvf_version": 1,
"source": {
"program": "vibe-qc",
"version": "0.9.0",
"calculation": "h2o_rhf_sto3g"
},
"sections": [
{
"id": "structure",
"kind": "structure",
"members": {
"structure": {
"path": "structure/structure.json",
"format": "json",
"sha256": "..."
}
}
}
]
}
Richer manifests may add:
{
"schema_uri": "https://vibe-qc.org/spec/qvf/1/manifest.schema.json",
"provenance": {
"method": "RKS",
"functional": "PBE",
"basis": "def2-SVP",
"charge": 0,
"multiplicity": 1,
"scf_converged": true,
"scf_energy": {"value": -76.3371, "units": "Eh"}
},
"thermochemistry": {
"zpve_eh": 0.0294,
"enthalpy_eh": -76.3077,
"entropy_cal_mol_k": 52.3,
"gibbs_free_energy_eh": -76.3321,
"temperature_k": 298.15,
"pressure_atm": 1.0
},
"dipole_moment": {
"total_debye": 1.85,
"vector_debye": [0.0, 0.0, 1.85],
"origin": "center_of_mass"
},
"constraints": {
"frozen_atoms": [3, 4],
"distance_constraints": [
{"atoms": [0, 1], "target_angstrom": 1.5}
]
},
"extensions": {
"x_vendor_ecp": {
"version": "1.0",
"schema_uri": "https://vendor.example.org/qvf/ecp.schema.json",
"critical": false
}
},
"viewer_defaults": {
"auto_open": ["vol_dens_0"],
"vol_dens_0": {"isovalue": 0.05, "colormap": "viridis", "opacity": 0.6},
"bookmarks": [
{
"name": "front",
"camera": {
"position": [0.0, 0.0, 12.0],
"focal_point": [0.0, 0.0, 0.0],
"view_up": [0.0, 1.0, 0.0],
"view_angle": 30.0
}
}
]
}
}
schema_uri is optional. The schema’s $id is still the
canonical identifier for the machine contract.
The manifest root may also carry optional metadata blocks:
thermochemistry— Thermodynamic corrections computed from the Hessian / frequency calculation. Fields:zpve_eh(zero-point vibrational energy in Hartree),enthalpy_eh,entropy_cal_mol_k,gibbs_free_energy_eh,temperature_k,pressure_atm. All fields are optional; a producer may emit only what it computed.dipole_moment— Electric dipole moment. Fields:total_debye,vector_debye(3-element array in Debye),origin(string naming the reference point:"center_of_mass","center_of_nuclear_charge", or"origin").constraints— Geometry optimization constraints. May carryfrozen_atoms(array of zero-based atom indices),frozen_lattice(bool), and constraint arrays:distance_constraints,angle_constraints,torsion_constraints. Each constraint hasatoms(indices) and atarget_*field with the target value.extensions— Extension governance block (see § 5). A mapping from vendor namespace to{"version": "...", "schema_uri": "...", "critical": true|false}. If a section with a matchingx_<vendor>.*kind hascritical: true, a consumer must either support it or refuse to open the file.
2.2 Section Objects¶
Every section has:
Field |
Required |
Meaning |
|---|---|---|
|
yes |
Unique section identifier within the archive. |
|
yes |
Section kind from the canonical registry or |
|
yes |
Mapping from member role to JSON or binary member spec. |
|
no |
Human-readable display label. |
|
no |
Component hint for sections such as |
|
no |
If |
|
no |
URI of a JSON Schema for this section’s members, overriding the kind’s canonical contract for vendor sections. |
JSON member spec:
{
"path": "structure/structure.json",
"format": "json",
"sha256": "64 lowercase hex characters"
}
Binary member spec:
{
"path": "volumes/rho.dat",
"format": "binary",
"dtype": "float32",
"shape": [80, 80, 80],
"sha256": "64 lowercase hex characters"
}
Binary members are raw C-contiguous NumPy-style arrays. The dtype is a NumPy dtype name from the schema enum. Current writer/reader behavior assumes ordinary little-endian platforms; adding an explicit endian tag is an open portability hardening item.
2.3 Validation¶
The canonical validator checks:
ZIP readability and a per-member uncompressed-size cap.
manifest.jsonexistence and JSON parseability.manifest conformance to the JSON Schema.
section id uniqueness.
declared member paths exist in the archive.
every declared member checksum matches the bytes on disk.
every JSON member parses as UTF-8 JSON.
every binary member’s byte length equals
dtype.itemsize * prod(shape).volume.difference.operand_a/operand_bresolve when present.reaction.waypoints.trajectory_refresolves to atrajectorysection.
The schema catches structural errors. validate_qvf() adds semantic
checks that JSON Schema cannot express cleanly.
3. Units And Numeric Conventions¶
QVF v1 uses fixed units per field. Producers convert at write time. Consumers may convert for display but should treat the on-disk units as the contract.
Field |
Unit / convention |
|---|---|
|
Angstrom |
|
Angstrom, row vectors |
|
bohr |
|
bohr per grid step |
|
electron density on a bohr grid, usually e / bohr^3 |
|
orbital amplitude on a bohr grid |
|
Angstrom |
|
Hartree |
|
Angstrom |
|
Hartree |
|
eV |
|
eV |
|
cm^-1 |
|
km / mol |
|
eV |
|
cm^-1 |
|
normal-mode displacement vectors, current writer convention |
|
bohr^-2 |
|
Hartree |
|
eV |
|
states / eV / cell (or spin channel) |
|
unitless (integrated count) |
|
eV |
|
states / eV / channel |
|
states / eV |
|
hartree / e (atomic units of potential) |
|
dimensionless ( |
|
eV (signed: E(k) − E_F) |
|
cm^-1 |
|
fractional reciprocal coordinates |
|
cm^-1 |
|
states / cm^-1 |
|
Angstrom^3 |
|
eV |
|
Angstrom^3 |
|
GPa |
|
unitless |
|
eV |
When adding fields, prefer unit-bearing names such as energy_eh,
energy_ev, frequency_cm, or a {"value", "units"} object.
4. Canonical Section Kinds¶
The v1 registry is the set of schema Section.* branches plus the
vendor namespace branch. The writer can emit the canonical kinds in the
table; vibe-view renders the listed supported subset.
Kind |
Payload |
Writer |
vibe-view |
|---|---|---|---|
|
Atoms, PBC flags, optional lattice |
yes |
yes |
|
Explicit connectivity table |
yes |
via structure renderer |
|
Scalar density grid |
yes |
yes |
|
Pre-sampled orbital grid |
yes |
yes |
|
Spin-density grid |
yes |
yes |
|
Electron localization function grid |
yes |
yes |
|
Difference scalar field with optional operand refs |
yes |
yes |
|
Generic scalar field escape hatch |
yes |
yes |
|
k-path metadata + rank-3 eigenvalue array |
yes |
yes |
|
IR frequency / intensity spectrum |
yes |
yes |
|
Raman spectrum |
yes |
yes |
|
UV/vis spectrum |
yes |
yes |
|
ECD spectrum |
yes |
yes |
|
VCD spectrum |
yes |
yes |
|
NMR chemical shifts / tensors / couplings |
yes |
yes |
|
Generic 1D spectrum |
yes |
yes |
|
Frames + optional energies |
yes |
yes |
|
Self-contained reaction path |
yes |
yes |
|
Waypoints over an existing trajectory |
yes |
yes |
|
Frequencies + displacement tensor |
yes |
yes |
|
Mulliken / Loewdin charges |
yes |
yes |
|
spglib-style symmetry summary |
yes |
yes |
|
SCF iteration records |
yes |
yes |
|
BibTeX bibliography bytes |
yes |
yes |
|
Molecular GTO basis + MO coefficients |
yes |
yes, with limitations |
|
Total density of states (energy grid + DOS) |
yes |
yes |
|
Projected DOS (per-atom, per-l-channel) |
yes |
yes |
|
Electrostatic potential on a grid |
yes |
yes |
|
Reduced density gradient (NCI analysis) |
yes |
yes |
|
3D k-space energy grid near Fermi level |
yes |
yes |
|
Phonon band structure (q-path + frequencies) |
yes |
yes |
|
Phonon density of states |
yes |
yes |
|
Volume-energy curve + fitted EOS params |
yes |
yes |
|
Vendor extension |
external producers |
listed, not rendered |
The reserved names volume.orbital_projection,
topology.qtaim, topology.elf_basins, and projections.lcao are
planning names. They are not portable v1 viewer contracts yet. External
producers should use x_<vendor>.* for experimental data until a kind
is promoted into the schema.
4.1 structure And bonds¶
structure carries atoms in Angstrom and optional lattice vectors:
{
"atoms": [
{"symbol": "O", "position": [0.0, 0.0, 0.1173], "atomic_number": 8},
{"symbol": "H", "position": [0.0, 0.7572, -0.4692], "atomic_number": 1}
],
"pbc": [false, false, false],
"lattice_vectors": null
}
For periodic systems, lattice_vectors is a [3, 3] array of row
vectors in Angstrom and pbc marks periodic axes.
Explicit connectivity is carried as a separate bonds section:
{
"pairs": [
{"i": 0, "j": 1, "order": 1.0},
{"i": 0, "j": 2, "order": 1.0}
]
}
If no bonds section is present, viewers may infer bonds from covalent
radii. Explicit bonds take precedence.
4.2 volume.*¶
All volume kinds use the same member shape:
{
"id": "vol_dens_0",
"kind": "volume.density",
"label": "Electron density",
"members": {
"grid": {"path": "volumes/Electron_density_grid.json", "format": "json", "sha256": "..."},
"data": {
"path": "volumes/Electron_density.dat",
"format": "binary",
"dtype": "float32",
"shape": [80, 80, 80],
"sha256": "..."
}
}
}
Grid JSON:
{
"origin": [-8.0, -8.0, -8.0],
"voxel_vectors": [
[0.2, 0.0, 0.0],
[0.0, 0.2, 0.0],
[0.0, 0.0, 0.2]
],
"shape": [80, 80, 80]
}
voxel_vectors is [v_i, v_j, v_k], three per-voxel step vectors in
bohr. For a data index (i, j, k), the point position is:
origin + i * v_i + j * v_j + k * v_k
This is point-centered data: the number of points in the rendered grid
matches shape, not shape + 1. Non-orthogonal grids are supported by
using non-zero off-diagonal vector components.
volume.difference may add operand_a and operand_b section ids.
If one operand is present, both are required. The sign convention is:
data = operand_a - operand_b
4.3 bands¶
Band eigenvalues are always rank 3:
{
"id": "bands0",
"kind": "bands",
"members": {
"kpath": {"path": "bands/kpath.json", "format": "json", "sha256": "..."},
"eigenvalues": {
"path": "bands/eigenvalues.bin",
"format": "binary",
"dtype": "float64",
"shape": [1, 100, 26],
"sha256": "..."
}
}
}
Shape is [n_spin, n_kpoints, n_bands]. Restricted calculations use
n_spin = 1. Energies are stored in eV.
The kpath JSON should include:
{
"kind": "bands",
"version": "1.0",
"n_spin": 1,
"n_kpoints": 100,
"n_bands": 26,
"fermi": -4.71,
"fermi_energy_ev": -4.71,
"reciprocal_space": true,
"segments": [
{
"label_start": "G",
"label_end": "X",
"k_start": [0.0, 0.0, 0.0],
"k_end": [0.5, 0.0, 0.0],
"n_points": 50
}
]
}
Consumers should accept either explicit segment start / end
indices or writer-style n_points segments.
4.4 Spectra¶
spectra.ir, spectra.raman, spectra.uvvis, spectra.ecd,
spectra.vcd, and spectra.generic each carry one JSON member named
spectrum. The common shape is:
{
"frequencies": [1000.0, 1500.0],
"intensities": [12.0, 4.5]
}
The physical meaning and units depend on kind. For example, IR uses cm^-1 and km/mol; UV/vis and ECD use eV on the x axis.
spectra.nmr is intentionally different. Its spectrum member is an
object with conventional optional keys:
{
"isotope": "1H",
"reference": "TMS",
"solvent": "gas",
"chemical_shifts": [
{"atom_index": 0, "symbol": "H", "isotropic_shift_ppm": 4.65}
],
"shielding_tensors": [],
"j_couplings": []
}
The schema intentionally keeps NMR payload shape loose in v1 while the field vocabulary settles.
4.5 Trajectories, Reactions, And Vibrations¶
trajectory has:
metadataJSON with atom identities and optional energies.coordsbinaryfloat64with shape[n_frames, n_atoms, 3]in Angstrom.
reaction.path uses the same coordinate layout and adds waypoint
records in metadata:
{
"waypoints": [
{"frame_index": 0, "label": "R", "kind": "reactant"},
{"frame_index": 7, "label": "TS", "kind": "transition_state", "energy_eh": -75.1}
],
"reaction_coordinate": [0.0, 0.2, 0.5]
}
reaction.waypoints carries only the annotations and references an
existing trajectory section through section-level trajectory_ref.
The validator checks that the reference resolves to a trajectory
section. Frame-bound validation is a desired future tightening.
vibrations carries:
metadataJSON with atoms and frequencies in cm^-1.displacementsbinary with shape[n_modes, n_atoms, 3].
4.6 wavefunction.gto¶
wavefunction.gto carries a molecular atom-centered Gaussian basis and
MO coefficient matrices:
{
"id": "wf",
"kind": "wavefunction.gto",
"members": {
"basis": {"path": "wavefunction/basis.json", "format": "json", "sha256": "..."},
"mo_metadata": {"path": "wavefunction/mo_metadata.json", "format": "json", "sha256": "..."},
"mo_coefficients": {
"path": "wavefunction/mo_coefficients.bin",
"format": "binary",
"dtype": "float64",
"shape": [41, 41],
"sha256": "..."
}
}
}
Unrestricted wavefunctions replace mo_coefficients with
mo_coefficients_alpha and mo_coefficients_beta.
basis JSON conventions:
structure_refnames the referencedstructuresection.centeris a zero-based atom index.lis shell angular momentum.exponentsare in bohr^-2.coefficientsapply to normalized primitive Gaussians.pure: truemeans spherical harmonics;falsemeans Cartesian.AO order is part of the contract: spherical
m = -l ... +l; Cartesian uses libint lexicographic ordering.
Limits in current reference viewer:
Molecular only; producers must not use this section for periodic Bloch wavefunctions.
vibe-view currently evaluates shells up to
l = 3for display. Higher-lbasis functions need a renderer extension or pre-sampledvolume.orbitalsections.
4.8 dos.total — Total Density of States¶
Carries the total electronic density of states, typically broadened with a Gaussian or Lorentzian smearing function:
{
"id": "dos_total",
"kind": "dos.total",
"members": {
"energies": {
"path": "dos/energies.bin",
"format": "binary",
"dtype": "float64",
"shape": [500],
"sha256": "..."
},
"dos": {
"path": "dos/total.bin",
"format": "binary",
"dtype": "float64",
"shape": [500],
"sha256": "..."
}
}
}
Both energies and dos are rank-1 arrays of the same length. For
spin-polarized calculations, dos is shape [2, n_points] (alpha,
beta channels). Energies are in eV, referenced to the Fermi level
(which is at 0.0 eV).
Metadata JSON (role meta) may carry:
{
"smearing": 0.05,
"smearing_type": "gaussian",
"fermi_energy_ev": -4.71,
"n_electrons": 64.0,
"n_spin": 1
}
n_electrons is the integrated count under the DOS — useful for
cross-checking and for Fermi-level interpolation.
4.9 dos.projected — Projected Density of States¶
Carries atom-projected and/or angular-momentum-projected DOS. The data is a flat rank-2 array where each row is one projection channel:
{
"id": "dos_pdos",
"kind": "dos.projected",
"members": {
"energies": {
"path": "dos/energies.bin",
"format": "binary",
"dtype": "float64",
"shape": [500],
"sha256": "..."
},
"projections": {
"path": "dos/projections.bin",
"format": "binary",
"dtype": "float64",
"shape": [12, 500],
"sha256": "..."
}
}
}
Metadata JSON (role meta) carries the channel descriptions:
{
"energies_units": "eV",
"n_spin": 1,
"fermi_energy_ev": -4.71,
"channels": [
{"atom_index": 0, "symbol": "Mg", "l": 0, "label": "Mg-3s"},
{"atom_index": 0, "symbol": "Mg", "l": 1, "label": "Mg-3p"},
{"atom_index": 1, "symbol": "O", "l": 0, "label": "O-2s"},
{"atom_index": 1, "symbol": "O", "l": 1, "label": "O-2p"}
]
}
Shape is [n_channels, n_points] for restricted or [n_spin, n_channels, n_points]
for spin-polarized. Consumers should check n_spin from the metadata
and interpret the leading dimension accordingly.
The dos.total and dos.projected kinds are deliberately separate
(rather than a single combined kind) so that a consumer doing only
total-DOS plotting can ignore the (potentially large) projection tensor.
4.10 volume.potential — Electrostatic Potential Grid¶
Promoted from reserved status to a canonical volume kind. Identical
member structure to volume.density (grid JSON + binary data), but the
data field carries the total electrostatic potential in hartree/e
(atomic units of potential):
{
"id": "esp",
"kind": "volume.potential",
"label": "Electrostatic potential",
"members": {
"grid": {"path": "volumes/esp_grid.json", "format": "json", "sha256": "..."},
"data": {
"path": "volumes/esp.dat",
"format": "binary",
"dtype": "float64",
"shape": [80, 80, 80],
"sha256": "..."
}
}
}
Visually, consumers typically render a single isosurface colored by the potential value (blue = positive, red = negative) or map the potential onto the solvent-accessible surface. vibe-view may offer both.
4.11 volume.rdg — Reduced Density Gradient (NCI Analysis)¶
The reduced density gradient s(r) = |∇ρ(r)| / (2(3π²)^⅓ ρ(r)^⅔) is the
key scalar field for Non-Covalent Interaction (NCI) analysis. Its
member structure matches volume.density:
{
"id": "rdg",
"kind": "volume.rdg",
"label": "Reduced density gradient",
"members": {
"grid": {"path": "volumes/rdg_grid.json", "format": "json", "sha256": "..."},
"data": {
"path": "volumes/rdg.dat",
"format": "binary",
"dtype": "float32",
"shape": [80, 80, 80],
"sha256": "..."
}
}
}
The data field carries the dimensionless s(r) value. Consumers that
also have a volume.density section in the archive should compute
sign(λ₂)ρ from the density (where λ₂ is the second eigenvalue of the
Hessian of ρ) and use it as the coloring field for the NCI isosurface
(standard convention: blue = attractive, green = van der Waals,
red = repulsive).
If the producer has already computed sign(λ₂)ρ, it may additionally
write a volume.density section with the sign(λ₂)ρ data for consumer
convenience.
4.12 fermi_surface — 3D Fermi Surface in Reciprocal Space¶
For metallic periodic systems, the Fermi surface is a 3D scalar field in reciprocal space: the signed distance from the Fermi level as a function of k-point for a selected band. The archive carries raw band energies on a Monkhorst–Pack mesh, and the consumer extracts isosurfaces at E = E_F:
{
"id": "fermi0",
"kind": "fermi_surface",
"members": {
"mesh": {
"path": "fermi/mesh.json",
"format": "json",
"sha256": "..."
},
"energies": {
"path": "fermi/energies.bin",
"format": "binary",
"dtype": "float64",
"shape": [10, 10, 10, 2],
"sha256": "..."
}
}
}
mesh JSON:
{
"nk1": 10,
"nk2": 10,
"nk3": 10,
"n_spin": 1,
"fermi_energy_ev": -4.71,
"band_indices": [3, 4],
"lattice_vectors": [[4.2, 0.0, 0.0], [0.0, 4.2, 0.0], [0.0, 0.0, 4.2]]
}
energies shape is [nk1, nk2, nk3, n_bands_near_fermi] — only bands
that cross or are within a window of ±2 eV (producer’s choice) of E_F.
The consumer renders a 3D isosurface at value = 0.0 (E_F) for each band,
optionally colored by band index or by spin channel.
The reciprocal-space grid is assumed gamma-centered and uniformly
spaced. lattice_vectors (in Angstrom, real space) enables the consumer
to draw the reciprocal cell wireframe.
4.13 phonon_bands And phonon_dos — Phonon Structure¶
phonon_bands¶
Parallel structure to electronic bands, but storing phonon frequencies
along a q-path in the Brillouin zone:
{
"id": "phonon_bands",
"kind": "phonon_bands",
"members": {
"qpath": {"path": "phonons/qpath.json", "format": "json", "sha256": "..."},
"frequencies": {
"path": "phonons/frequencies.bin",
"format": "binary",
"dtype": "float64",
"shape": [1, 100, 24],
"sha256": "..."
}
}
}
frequencies shape is [n_qpts, n_modes] (3 × n_atoms modes).
Frequencies are in cm⁻¹. Producers should ensure acoustic modes start
near zero; consumers should not display or highlight negative
(imaginary) frequencies unless explicitly requested.
qpath JSON:
{
"n_atoms": 8,
"n_modes": 24,
"has_eigenvectors": false,
"segments": [
{
"label_start": "G",
"label_end": "X",
"k_start": [0.0, 0.0, 0.0],
"k_end": [0.5, 0.0, 0.0],
"n_points": 50
}
]
}
Optional: if eigenvectors are available, an additional eigenvectors
binary member (shape [n_qpts, n_modes, n_atoms, 3], float64) carries
the displacement vectors for animated display. has_eigenvectors: true
in the metadata tells the consumer to load them.
phonon_dos¶
{
"id": "phonon_dos",
"kind": "phonon_dos",
"members": {
"meta": {"path": "phonons/dos_meta.json", "format": "json", "sha256": "..."},
"frequencies": {
"path": "phonons/dos_freq.bin",
"format": "binary",
"dtype": "float64",
"shape": [500],
"sha256": "..."
},
"dos": {
"path": "phonons/dos_total.bin",
"format": "binary",
"dtype": "float64",
"shape": [500],
"sha256": "..."
}
}
}
Metadata meta may carry smearing, smearing_type, n_atoms,
n_modes. Optionally, a projected binary member (shape
[n_atoms, n_points]) carries atom-projected phonon DOS.
4.14 equation_of_state — EOS Curve And Fit¶
Carries the raw volume-energy points from a series of periodic calculations at varying unit-cell volumes, plus the fitted EOS parameters:
{
"id": "eos",
"kind": "equation_of_state",
"members": {
"volumes": {
"path": "eos/volumes.bin",
"format": "binary",
"dtype": "float64",
"shape": [15],
"sha256": "..."
},
"energies": {
"path": "eos/energies.bin",
"format": "binary",
"dtype": "float64",
"shape": [15],
"sha256": "..."
},
"fit": {
"path": "eos/fit.json",
"format": "json",
"sha256": "..."
}
}
}
fit JSON:
{
"model": "birch_murnaghan",
"V0": 120.4,
"E0": -5000.23,
"B0": 74.2,
"B0_prime": 4.1,
"energy_unit": "eV",
"volume_unit": "angstrom^3",
"pressure_unit": "GPa",
"residual_rms": 1.2e-5,
"pressures_gpa": [null, -0.2, 0.0, 0.3]
}
The pressures_gpa array (same length as volumes) reports the
pressure at each point from the EOS fit, or null if the point was
excluded. residual_rms is the RMS deviation of the fit from the
raw points.
Supported model values: "birch_murnaghan" (3rd order,
E(V) = E0 + 9V0B0/16 · {[(V0/V)^(2/3) − 1]³ · B0’ + [(V0/V)^(2/3) − 1]² · [6 − 4(V0/V)^(2/3)]}),
"murnaghan", "vinet".
4.7 Provenance, Citations, And SCF History (Updated)¶
Root source is mandatory and intentionally small:
{"program": "vibe-qc", "version": "0.9.0", "calculation": "job_name"}
Root provenance is optional and carries calculation-level metadata
such as method, basis, functional, charge, multiplicity, convergence,
and unit-tagged energies.
citations carries one binary member, references, containing UTF-8
BibTeX bytes.
scf_history carries one JSON member, iterations:
{
"iterations": [
{"iter": 1, "energy_eh": -75.0, "delta_e": 1.0, "diis_error": 1e-2}
]
}
Fields are conventional in v1. Consumers should degrade gracefully when a solver does not report DIIS error or energy deltas.
Beyond section-level records, the manifest root may carry additional metadata as documented in § 2.1:
thermochemistry— ZPVE, enthalpy, entropy, Gibbs free energy.dipole_moment— Total and vector dipole moment in Debye.constraints— Geoemtry optimization constraints (frozen atoms, distance/angle/torsion targets).
These are root-level objects, not sections, because they describe the calculation as a whole rather than carrying binary payloads. A consumer may display them in the application bar, a property panel, or omit them gracefully.
5. Extension And Versioning Model¶
QVF v1.1 establishes a formal extension governance model built on four
mechanisms: the root extensions block, the per-section critical
flag, the per-section schema_uri, and a minor-version convention for
adding canonical optional kinds.
5.1 qvf_version Policy¶
qvf_version is an integer. v1.0 = 1. v1.1 = 1 (the extension
governance and new canonical kinds are backward-compatible additions).
Major version bumps (qvf_version: 2, …) indicate breaking changes:
removed kinds, mandatory-become-optional inversions, or incompatible
unit changes. Minor version is not encoded in the integer; instead,
consumers detect capability from the extension block and supported-kind
checking.
If future major versions are needed, a qvf_version value > 1 means
consumers that only understand qvf_version = 1 MUST refuse to open
the file.
5.2 Canonical Kinds¶
Canonical kinds appear in the JSON Schema and are described in § 4. The set of canonical kinds may grow in minor revisions (new kinds added, existing kinds extended with optional members). No canonical kind may be removed or have its required members changed without a major version bump.
5.3 Vendor Namespace (x_<vendor>.*)¶
Any section with a kind matching x_<vendor>.<specific> is a vendor
extension. The <vendor> part should be a DNS-like identifier
(e.g. x_vibeqc, x_pyscf, x_vasp, x_orca).
Vendor members must still be valid JSON or binary member specs.
A consumer must list vendor sections as present but unsupported, unless the extension is declared as
critical: true(see § 5.5).Unknown non-vendor kinds (no
x_prefix, not in the canonical registry) are not schema-valid QVF and should be reported as errors.
5.4 Root extensions Block¶
The manifest root may carry an extensions object that declares which
vendor extensions are in use and their contracts:
{
"extensions": {
"x_vendor_ecp": {
"version": "1.0",
"schema_uri": "https://vendor.example.org/qvf/ecp.schema.json",
"critical": false
},
"x_other_plugin": {
"version": "2.1",
"critical": true
}
}
}
Each key is a vendor namespace prefix (without the x_ — the x_ is
implied from the section kinds). The value object has:
Field |
Required |
Meaning |
|---|---|---|
|
yes |
Vendor’s own version string for this extension. |
|
no |
URI of a JSON Schema that validates this extension’s section members. |
|
no |
If |
5.5 Per-section critical Flag¶
Every section object in sections[] may carry a critical boolean
(default false). If critical: true and the consumer does not
recognize or support that kind, the consumer MUST refuse to open
the file entirely rather than silently ignoring the section.
This prevents data loss in workflows where an extension carries information essential to correct interpretation (e.g., an ECP specification that changes the effective number of electrons, or a custom energy correction that alters displayed energies).
5.6 Minor-Version Convention¶
Canonical kinds may be added in minor revisions. A producer targeting
qvf_version: 1 may emit any canonical kind defined in the current
schema. A consumer targeting qvf_version: 1 must accept any file
where it either supports the kind or the kind is non-critical.
There is no explicit minor_version field. Extensions are the
mechanism for signaling non-canonical capability.
5.7 Registry Process For Promoting Vendor Kinds¶
To promote an x_<vendor>.* kind to canonical status:
The kind is used in production by at least two independent producers for at least one minor release cycle.
A specification PR adds the kind to § 4, the JSON Schema
Section.oneOfbranches, and updates the validator.The kind’s member contract is stable across the two producers.
At least one reference consumer implements rendering support.
This process is intentionally lightweight in v1.x to encourage rapid adoption, and may be formalized in v2.
6. Producer Contract¶
A conforming producer must:
write a valid ZIP archive with
manifest.json;set
qvf_versionto1;include
source.program,source.version, andsource.calculation;use unique section ids;
use canonical kinds or
x_<vendor>.*;include only manifest member paths that exist in the ZIP;
compute sha256 over the exact bytes stored in the ZIP;
write numeric fields in the units specified above;
write binary payloads matching declared dtype and shape;
ensure JSON members parse as UTF-8 JSON;
declare every
x_<vendor>namespace used insections[]in the rootextensionsblock whencritical: trueis set on any section in that namespace;set
critical: trueon a section only if the producer truly requires consumer support for correct interpretation (see § 5.5).
A producer should:
include
provenancewhenever the calculation context is known;include
citationswhen results depend on citable methods, bases, functionals, ECPs, libraries, or external data;use
volume.genericonly when no specificvolume.*kind applies;use vendor namespaces for experimental payloads;
ship small examples and run
validate_qvf()in tests.
7. Consumer Contract¶
A conforming consumer must:
read
manifest.jsonby name rather than assuming ZIP entry order;validate or at least sanity-check
qvf_version,source, andsections;verify sha256 before using a member’s bytes;
interpret only section kinds it supports;
report unsupported vendor sections without corrupting or misinterpreting them;
respect declared dtype, shape, and units;
check per-section
criticalflag: ifcritical: trueand the kind is not supported, refuse to open the file;check root
extensionsblock forcritical: trueextensions that are not supported and refuse accordingly.
A consumer may require specific kinds for a particular operation. For
example, a band plotter may refuse a file without bands, while a
structure viewer may open the same file and ignore all scalar fields.
8. vibe-view Reference Implementation¶
vibe-view/ is the current reference consumer. It is a peer
sub-project, not part of the lightweight vibeqc import path.
Install from a checkout:
pip install -e '.[viewer-gpu]'
vibe-view open my-calculation.qvf
Core modules:
vibe-view/src/vibeview/
├── qvf.py # QVFReader: zip, schema, sha256, lazy reads
├── kinds.py # SUPPORTED_KINDS and lazy-kind registry
├── schema.json # symlink to canonical manifest schema
├── viewer_defaults.py # camera, volume hints, replication
├── renderers/
│ ├── structure.py
│ ├── volume.py
│ ├── bands.py
│ ├── spectra.py
│ ├── trajectory.py
│ ├── vibrations.py
│ ├── reaction.py
│ ├── wavefunction.py
│ ├── atom_properties.py
│ ├── nmr.py
│ ├── scf_history.py
│ ├── symmetry.py
│ └── citations.py
└── app.py # Trame / PyVista UI
vibe-view uses PyVista, VTK, Trame, Plotly, Pydantic, jsonschema, and NumPy. It lazy-loads volume binary blobs and verifies member checksums before use.
9. Implementation Pointers¶
Schema:
python/vibeqc/output/formats/qvf_manifest.schema.jsonViewer reader:
vibe-view/src/vibeview/qvf.pyViewer kind registry:
vibe-view/src/vibeview/kinds.pyUser guide:
docs/user_guide/vibe_view.mdReference consumer example:
docs/consumer_qvf_reference.md
Relevant tests:
tests/test_qvf_writer.pytests/test_qvf_round_trip.pytests/test_qvf_writer_to_viewer.pyvibe-view/tests/test_qvf.pyvibe-view/tests/test_renderer_behaviour.pyvibe-view/tests/test_qvf_schema_identity.py
10. Open Design Items¶
These are intentionally not hidden:
Endianness. The current dtype names do not carry byte order. v1 assumes the normal little-endian scientific-Python ecosystem. A byte-order prefix in dtype (e.g.,
">f4") should be added for cross-platform portability in v1.2.Periodic wavefunctions.
wavefunction.gtois molecular only. Bloch coefficients need a separate section kind (e.g.wavefunction.blochorwavefunction.kohn_sham).Topology payloads. QTAIM and ELF basin data are reserved ideas, not v1 contracts. A
topology.qtaimandtopology.elf_basinssection kind remains to be specified.Large time-dependent volumes. v1 handles individual scalar fields well; long volumetric movies may need chunking conventions, a time axis in the grid descriptor, or an explicit frame-based volume kind.
NMR schema tightening.
spectra.nmris intentionally loose in v1 while producer conventions settle. A v1.2 tightening pass should define chemical-shift tensor, J-coupling tensor, and relaxation-time structures.Fermi-surface grid conventions.
fermi_surfaceuses a gamma-centered Monkhorst-Pack grid in v1.1. A future revision may need to support arbitrary k-mesh geometries (tetrahedron integration meshes, band-structure k-paths cross-sampled onto the FS grid).Phonon eigenvectors. The optional
eigenvectorsmember inphonon_bandsuses displacement vectors in Cartesian coordinates. The exact normalization and phase conventions should be documented explicitly in a future tightening pass.EOS fit validation. The
equation_of_statesection carries only the fit parameters, not the raw derivative data (pressure, bulk modulus as a function of volume). A future revision may add optional derivative arrays for interactive EOS exploration.
The format is useful now. These items define the next layer needed for QVF to become a durable multi-code standard rather than only a strong vibe-qc/vibe-view interchange format.