Design — basis.ao section for basis-function visualization¶
Status: Proposed, not yet implemented. Target: QVF v1 (backward-compatible addition as an optional canonical kind). Depends on: existing QVF writer (
qvf.py), cube grid evaluators (cube.py), vibe-view volume renderer + sidebar grouping pattern.
1. Motivation¶
Basis-set optimization workflows need to answer spatial questions that energy tables alone cannot:
“Is this diffuse exponent bleeding 3–4 unit cells away?”
“Does the contraction give enough angular resolution at the atom?”
“Are there pathological shell overlaps across cell boundaries?”
“Did the optimizer shrink the rogue diffuse, or did it lose needed flexibility?”
Answering these requires per-AO isosurfaces — the ability to select a single atomic orbital (primitive or contracted shell), render its isosurface in the crystal lattice, and compare before/after optimization.
This document defines the basis.ao section kind that delivers that
capability through the existing QVF + vibe-view pipeline.
2. Section kind: basis.ao¶
basis.ao is a volume-like section that carries one atomic orbital’s
scalar field on a 3-D grid, plus structured metadata that describes
which basis function it represents.
2.1 Manifest shape¶
{
"id": "ao_H_1s_s0_p0",
"kind": "basis.ao",
"label": "H 1s — exp=0.12 coeff=0.15",
"ao_metadata": {
"atom_index": 0,
"atom_symbol": "H",
"shell_index": 0,
"primitive_index": 0,
"angular_momentum": [0, 0],
"shell_type": "s",
"exponent": 0.12,
"coefficient": 0.15,
"is_primitive": true,
"is_contracted": false,
"ao_index": 0,
"basis_label": "pob-TZVP"
},
"members": {
"grid": {
"path": "basis_ao/H_1s_s0_p0_grid.json",
"format": "json",
"sha256": "…"
},
"data": {
"path": "basis_ao/H_1s_s0_p0.dat",
"format": "binary",
"dtype": "float32",
"shape": [80, 80, 80],
"sha256": "…"
}
}
}
2.2 ao_metadata fields¶
All fields are required unless marked optional. This is a section-level
object (sibling to id, kind, members), not a zip member — the
metadata is embedded directly in manifest.json for random-access
discovery without reading any payload bytes.
Field |
Type |
Description |
|---|---|---|
|
|
Zero-based index into the |
|
|
Element symbol (denormalized convenience, e.g. |
|
|
Which contracted shell within the atom’s basis block (0-based). |
|
|
Which primitive Gaussian within the shell. For contracted shells (when |
|
|
|
|
|
One of |
|
|
Gaussian exponent α in bohr⁻². |
|
|
Normalized contraction coefficient for this primitive. For contracted shells this is the contraction coefficient of the first primitive. |
|
|
|
|
|
|
|
|
Global AO index (0-based) within the full basis set. Used to cross-reference the |
|
|
Human-readable basis set name, e.g. |
Invariants:
is_primitiveandis_contractedare mutually exclusive. Exactly one istrue.When
is_primitiveistrue,primitive_indexnames the specific primitive within the shell.When
is_contractedistrue,primitive_indexis informational (identifies the first primitive of that shell), and theexponent/coefficientvalues refer to that first primitive as a representative.ao_indexis globally unique across allbasis.aosections referencing the same basis set.
2.3 Members¶
Member |
Format |
Required |
Description |
|---|---|---|---|
|
|
yes |
Same grid descriptor as all |
|
|
yes |
Rank-3 array, point-centered. The scalar field χ(r) evaluated at each voxel. |
The grid + data contract is identical to volume.orbital (design § 4.2).
This means vibe-view’s VolumeRenderer can render a basis.ao section
with zero code changes — the renderer dispatch just needs to map
basis.ao → VolumeRenderer.
2.4 Id convention¶
Producers should use stable, human-readable ids:
ao_{symbol}_{shell_type}_s{shell_idx}_p{prim_idx}
Examples:
ao_H_s_s0_p0— H atom, s shell, primitive 0ao_O_sp_s2_p1— O atom, sp shell, primitive 1ao_O_d_s3_contracted— O atom, d shell, contracted
These ids appear in the vibe-view AO picker dropdown and in
viewer_defaults.auto_open. Consumers must tolerate any valid
^[A-Za-z0-9_.-]+$ id.
3. Viewer defaults¶
Per-section hints in viewer_defaults:
{
"viewer_defaults": {
"auto_open": ["ao_O_sp_s1_p0"],
"ao_H_s_s0_p0": {
"isovalue": 0.03,
"colormap": "RdBu",
"opacity": 0.5
}
}
}
3.1 Sensible defaults¶
The producer should compute per-AO default isovalues based on the exponent, so the first render is informative:
Exponent range |
Default isovalue |
Rationale |
|---|---|---|
α < 0.1 (very diffuse) |
0.005 |
Diffuse functions have low peak amplitude; a high isovalue shows nothing. |
0.1 ≤ α < 1.0 (diffuse) |
0.02 |
|
1.0 ≤ α < 10 (moderate) |
0.05 |
Standard. |
α ≥ 10 (tight) |
0.10 |
Tight functions have high peak amplitude at the nucleus. |
Default colormap: "RdBu" (diverging) — essential for p, d, f functions
that have positive and negative lobes.
Default opacity: 0.5.
Default grid spacing: 0.15 bohr (finer than the 0.25 bohr density default, because individual primitives can be spatially compact).
Default grid padding: 8.0 bohr (wider than the 4.0 bohr molecular default, to capture diffuse-functions extending across unit cells).
3.2 Grid for periodic systems¶
For periodic systems the grid should:
Span the unit cell (or a user-specified N×M×L supercell).
Have
originat the unit-cell origin (atoms in the reference cell are inside the grid).Use axis-aligned
voxel_vectorsfor orthogonal cells; follow lattice vectors for non-orthogonal cells.Evaluate the AO only at the reference atom position — do not replicate AOs across image cells. vibe-view’s periodic replication controls handle the visual tiling.
Grid origin and voxel vectors remain in bohr per the QVF v1 contract (design § 1.3a).
4. Which AOs to export by default¶
The producer should accept a filter specification. Sensible presets:
4.1 “Optimised” mode (default for basis-optimization workflows)¶
Export only the primitives that are free parameters in the
optimization. The FreeSpec list from vibeqc.basis_optimization.parametrise
tells us exactly which exponents/coefficients the optimizer varied.
Additionally export the most diffuse and most contracted primitive per shell as reference points.
4.2 “Valence” mode¶
Export only shells with principal quantum number ≥ the highest core shell (typically: valence + polarisation shells).
4.3 “All” mode¶
Export every primitive and every contracted shell for every atom. This produces the largest QVF — for a pob-TZVP basis on a 2-atom cell (~30 shells, ~4 primitives/shell, ~150 AOs total), at 80³ grid points × 4 bytes × 150 AOs ≈ 307 MB in the zip (typically ~100 MB compressed).
4.4 Filtering API¶
The convenience builder should accept:
qvf_ao_data(
basis, system_or_mol,
*,
atom_indices: list[int] | None = None, # which atoms
shell_types: list[str] | None = None, # e.g. ["s", "p", "d"]
ao_indices: list[int] | None = None, # explicit AO indices
primitive_only: bool = False, # skip contracted shells
contracted_only: bool = False, # skip individual primitives
mode: str = "all", # "all" | "optimised" | "valence"
spacing: float = 0.15, # bohr
padding: float = 8.0, # bohr
)
5. vibe-view integration¶
5.2 Right panel — AO picker¶
The right panel shows a card with:
Basis Functions
┌─────────────────────────────────┐
│ Filter by atom: [All ▼] │
│ Filter by l: [All ▼] │
│ Mode: [Primitives ▼]│
│ │
│ AO: [H 2s — α=0.12 ▼] │
│ Exponent: 0.120 bohr⁻² │
│ Coefficient: 0.150 │
│ Center: H (atom 0) │
│ Shell type: s (l=0, m=0) │
│ Global AO index: 0 │
└─────────────────────────────────┘
The AO dropdown items have descriptive labels:
H 1s — α=0.120 (primitive)
H 1s — α=0.350 (primitive)
H 1s (contracted) (contracted shell)
O 2sp — α=0.185 (primitive)
O 3d_z² — α=3.500 (primitive)
O 3d (contracted) (contracted shell)
Filter dropdowns let the user narrow by atom, angular momentum, and primitive vs. contracted.
The isosurface controls (isovalue, colormap, opacity, clip planes,
replication) are the same shared panel used by all volume.* sections.
5.3 Renderer dispatch¶
basis.ao maps to VolumeRenderer in renderers/__init__.py.
The rendering path is identical to volume.orbital since the member
layout (grid + data) is the same.
5.4 Before/after comparison¶
The planned multi-file support (open user request #3 from the vibe-view handover) is the natural comparison mechanism: open two QVFs (pre- and post-optimization), select the same AO in each, switch between them in the file dropdown.
6. Producer contract¶
A conforming producer must:
Use kind
"basis.ao".Include
ao_metadatawith all required fields at the section root.Provide
grid(JSON) anddata(binary, 3-D) members following thevolume.*contract.Set
is_primitivexoris_contractedtotrue.Follow the id convention or use any valid
^[A-Za-z0-9_.-]+$id.
A producer should:
Compute per-AO
viewer_defaultshints with sensible isovalues (see § 3.1).Include
basis_labelwhen the basis set has a known name.Use
float32for the data member unlessfloat64precision is genuinely needed.Export only the AOs relevant to the workflow (see § 4).
7. Consumer contract¶
A conforming consumer must:
Treat
basis.aoas a volume section with per-AO metadata.Verify sha256 before rendering.
Respect the
ao_metadatafields for labeling and grouping.
A consumer should:
Collapse multiple
basis.aosections into a single navigable group.Provide filtering by atom, angular momentum, and primitive/contracted.
Display the AO metadata alongside the isosurface.
8. Relationship to wavefunction.gto¶
Aspect |
|
|
|---|---|---|
What it carries |
Full basis spec + MO coefficient matrix |
One pre-computed AO scalar field |
Compute location |
Consumer evaluates AOs internally |
Producer evaluates, consumer renders |
Scope |
Molecular only (v1) |
Molecular + periodic |
Use case |
Interactive MO explorer |
Basis inspection, optimization diagnostics |
File size |
~KB (basis JSON + MO matrix) |
~MB per AO (3-D grid) |
Viewer renders |
Isosurface on demand |
Pre-computed isosurface |
The two are complementary. A QVF may contain both. When both are
present, ao_metadata.ao_index cross-references the AO in
wavefunction.gto.basis.
9. JSON Schema addition¶
A new SectionBasisAO definition branch is added to the Section.oneOf
array in qvf_manifest.schema.json:
"SectionBasisAO": {
"properties": {
"kind": {"const": "basis.ao"},
"ao_metadata": {
"type": "object",
"additionalProperties": false,
"required": [
"atom_index", "atom_symbol", "shell_index", "primitive_index",
"angular_momentum", "shell_type", "exponent", "coefficient",
"is_primitive", "is_contracted", "ao_index"
],
"properties": {
"atom_index": {"type": "integer", "minimum": 0},
"atom_symbol": {"type": "string", "minLength": 1, "maxLength": 3},
"shell_index": {"type": "integer", "minimum": 0},
"primitive_index":{"type": "integer", "minimum": 0},
"angular_momentum":{
"type": "array",
"items": {"type": "integer"},
"minItems": 2, "maxItems": 2
},
"shell_type": {"type": "string", "enum": ["s","p","sp","d","f","g","h"]},
"exponent": {"type": "number", "exclusiveMinimum": 0},
"coefficient": {"type": "number"},
"is_primitive": {"type": "boolean"},
"is_contracted": {"type": "boolean"},
"ao_index": {"type": "integer", "minimum": 0},
"basis_label": {"type": "string"}
}
},
"members": {
"type": "object",
"additionalProperties": false,
"required": ["grid", "data"],
"properties": {
"grid": {"$ref": "#/$defs/JsonMember"},
"data": {"$ref": "#/$defs/Volume3DBinary"}
}
}
}
}
10. Reserved future kinds¶
The following related kind names are reserved for forward compatibility but are not implemented:
Kind |
Purpose |
|---|---|
|
2-D AO overlap matrix heatmap (S_{μν}) |
|
Real-space basis completeness map (sum of all AO densities on a grid) |
|
Difference field between two basis sets (ρ_basis_A − ρ_basis_B) |
11. Implementation plan¶
Step |
What |
Where |
Depends on |
|---|---|---|---|
1 |
|
|
— |
2 |
|
|
— |
3 |
|
|
1, 2 |
4 |
|
|
3 |
5 |
|
|
4 |
6 |
|
|
4, 5 |
7 |
|
|
— |
8 |
Sidebar grouping (“Basis Functions (N)”) + AO picker panel |
|
7 |
9 |
Showcase example script |
|
4, 8 |
10 |
Tests: writer round-trip, schema validation, viewer activation |
|
4, 5, 8 |
Steps 1–6 are producer-side; 7–8 are consumer-side; they can proceed in parallel once step 4 (the manifest contract) is finalized.