Tutorial 45: vibe-view end-to-end walkthrough¶
You will learn: how to produce a .qvf archive from a routine
vibe-qc job, launch vibe-view, and
inspect every section the calculation wrote: structure, electron
density, the HOMO / LUMO orbitals, the optimisation trajectory, the
IR spectrum, and the per-job citation bundle.
Prerequisites:
vibeqcinstalled and a working SCF setup (any tutorial under Fundamentals shows this).vibe-viewinstalled: from the vibe-qc checkout root eitherpip install -e '.[viewer-gpu]'(with vibe-qc) orpip install -e vibe-view/(standalone). VTK is ~200 MB so the first install is slow.A working modern browser (Chrome, Firefox, Safari, Edge). vibe-view uses Trame + WebSocket; very strict ad-blockers can interfere.
Time to complete: about 5 minutes.
1. Produce a .qvf¶
Anything in vibe-qc that runs through run_job or run_periodic_job
can emit a .qvf by passing output_qvf=True. Here is a small
RKS / PBE / 6-31G* water calculation with everything that vibe-view
knows how to render:
# input-water-vibe-view.py
from vibeqc import Atom, Molecule, run_job
mol = Molecule([
Atom(8, [0.0, 0.00, 0.00]),
Atom(1, [0.0, 1.43, -0.98]),
Atom(1, [0.0, -1.43, -0.98]),
])
run_job(
mol,
basis="6-31g*",
method="rks",
functional="PBE",
optimize=True, # writes a trajectory section
hessian=True, # writes vibrations + IR spectrum
output="water",
output_qvf=True, # produces water.qvf
write_density=True, # embeds the SCF density isosurface
write_molden_file=True, # embeds wavefunction.gto + MO blobs
)
Run it (a few seconds on any modern laptop):
~/path/to/vibeqc/.venv/bin/python input-water-vibe-view.py
Output:
water.out . banner + SCF trace + geometry opt log
water.molden . MO coefficients (Avogadro / Jmol)
water.traj . ASE trajectory (ase gui water.traj)
water.bibtex . auto-assembled BibTeX entries
water.references . Chicago-style reference list
water.system . TOML manifest with hardware + library versions
water.qvf . what we will open in vibe-view in a second
Have a peek at the manifest to confirm the sections vibe-view will render:
import zipfile, json
manifest = json.loads(zipfile.ZipFile("water.qvf").read("manifest.json"))
for s in manifest["sections"]:
print(f" {s['id']:<15s} {s['kind']}")
Typical output:
structure structure
density volume.density
homo volume.orbital
lumo volume.orbital
wavefunction wavefunction.gto
traj0 trajectory
vib vibrations
ir spectra.ir
citations citations
scf_history scf_history
2. Launch vibe-view¶
vibe-view open water.qvf
Two things happen:
Startup banner prints to stdout (the same table you printed from the manifest above, with per-section render status):
╔══════════════════════════════════════════════════════════════════════════════╗ ║ QVF file: water.qvf ║ ║ Source: vibe-qc 0.9.0 - water ║ ╠══════════════════════════════════════════════════════════════════════════════╣ ║ structure structure rendered ║ ║ density volume.density rendered ║ ║ homo volume.orbital rendered ║ ║ lumo volume.orbital rendered ║ ║ wavefunction wavefunction.gto rendered ║ ║ traj0 trajectory rendered ║ ║ vib vibrations rendered ║ ║ ir spectra.ir rendered ║ ║ citations citations rendered ║ ║ scf_history scf_history rendered ║ ╚══════════════════════════════════════════════════════════════════════════════╝
The default browser opens at
http://127.0.0.1:8080with the 3D viewport. The server stays in the foreground; press Ctrl+C in the terminal to stop it.
Tips:
vibe-view open water.qvf --port 9876 # different port
vibe-view open water.qvf --no-browser # do not auto-open the browser
vibe-view open water.qvf --host 0.0.0.0 # bind to all interfaces (remote use)
3. Walk through what each panel does¶
The browser window has three regions:
Top bar: source banner (program + version + calculation name) and the active-section pill.
Sidebar (left): every section from the manifest, classified as rendered / skipped / error. Click any section to make it active.
Viewport (centre): 3D scene for structure / volume / trajectory / vibrations, interactive Plotly for bands / spectra, table for
atom_properties/scf_history/citations.
Structure¶
The first section that auto-activates is structure. You see the
H2O molecule with CPK-coloured atoms (red oxygen, white hydrogens)
and bonds drawn from covalent radii. Rotate with left-drag, pan
with middle-drag, zoom with the scroll wheel.
Electron density¶
Click density in the sidebar. vibe-view marches the cubes at
the default isovalue of 0.05 e/bohr^3 and renders the resulting
isosurface translucent over the structure. A sidebar control lets
you change the isovalue (lower values give a larger lobe; higher
values squeeze in toward the nuclei).
This is the right place to see what the SCF actually converged on. For water the lone-pair region behind the oxygen should be the largest pocket of density.
Molecular orbitals (HOMO + LUMO)¶
Click homo. vibe-view marches the cubes on the orbital .dat
payload (real-valued for closed-shell molecular MOs). Because MOs
have signed lobes the viewer uses a divergent colormap by default,
so you can see the + and - regions. Set the isovalue to ~0.04
bohr^(-3/2) for the standard “balloon” view of an HF-style HOMO.
Click lumo to see the LUMO instead. Both stay loaded; the
viewport always shows the active section’s volume.
The full MO set via wavefunction.gto¶
For more orbitals than just HOMO / LUMO, click wavefunction.
vibe-view shows a list of every MO (with energy and occupation) and
re-samples each MO from the basis + coefficients when you click it.
This is cheaper to produce than writing every MO as a separate
volume.orbital section.
Geometry-optimisation trajectory¶
Click traj0. The viewport switches to a frame-by-frame
animation of the geometry-optimisation steps. A play / pause / step
strip below the viewport drives the timeline; a small energy chart
above it plots the per-frame energies (in Hartree) so you can see
the SCF energy decrease monotonically.
For our water optimisation there are only a few frames because the input geometry was already near the minimum; the energy chart drops by a fraction of a mHa and the structure barely moves.
Vibrational modes¶
Click vib. The viewport renders the equilibrium geometry; a
dropdown selector lets you pick a normal mode by frequency (in
cm^-1). The atoms oscillate along the displacement vector with the
mode’s amplitude.
For water at HF/6-31G* you should see three modes near 1700, 3900, and 4000 cm^-1: the symmetric bend, the symmetric stretch, and the antisymmetric stretch. The stretches mostly move the hydrogens; the bend mostly moves the oxygen.
IR spectrum¶
Click ir. The viewport switches to an interactive Plotly stem
chart of intensities vs frequency. Hover any peak to see the exact
frequency and intensity (in km / mol). The chart respects the
viewer-defaults x-axis range if the producer set one.
Citations¶
Click citations at the bottom of the sidebar. The viewport
shows the embedded BibTeX bundle as a copy-paste block: every paper
the run cites (vibe-qc itself, libint, libxc, PBE, the basis set,
plus any dispersion / SCF-accelerator references). This is the same
bundle written to water.bibtex on disk; see the
citations user guide for the format
spec.
SCF history¶
Click scf_history. Two stacked Plotly panes:
Top: SCF energy vs iteration (Hartree).
Bottom:
|DIIS error|vs iteration (log scale).
Hover any iteration to see the exact numbers. This is the same
information vibe-qc writes to water.out as a text table, presented
as a chart you can zoom and pan.
4. Periodic example: MgO bands¶
Periodic systems work the same way. For an MgO rocksalt RHF calculation with an embedded band structure:
# input-mgo-vibe-view.py
import numpy as np
import vibeqc as vq
a = 4.21 / 0.529177 # Angstrom to bohr
mgo = vq.PeriodicSystem(
3,
np.eye(3) * a,
[vq.Atom(12, [0.0, 0.0, 0.0]),
vq.Atom(8, [a/2, a/2, a/2])],
)
basis = vq.BasisSet(mgo.unit_cell_molecule(), "sto-3g")
# Compute a band structure along a high-symmetry path. Each segment
# is (start_frac, start_label, end_frac, end_label).
kpath = vq.kpath_from_segments(
mgo,
segments=[
([0.0, 0.0, 0.0], "G", [0.5, 0.0, 0.5], "X"),
([0.5, 0.0, 0.5], "X", [0.5, 0.5, 0.5], "L"),
([0.5, 0.5, 0.5], "L", [0.0, 0.0, 0.0], "G"),
],
points_per_segment=20,
)
vq.run_periodic_job(
mgo,
basis=basis,
method="RHF",
output="mgo",
output_qvf=True,
write_density=True,
band_structure=vq.band_structure_hcore(mgo, basis, kpath),
)
vibe-view open mgo.qvf
Two extra sidebar entries appear compared to the molecular case:
structurenow shows a unit-cell wireframe. Sidebar gains a replication control (Nx, Ny, Nz) to extend the cell along the lattice vectors. Atoms, the cell box, and any active isosurface all expand together.bandsopens the Plotly band plot: every band’s eigenvalue along the k-path, with a horizontal line at the Fermi energy. Hover any band to see the energy in eV.
5. Tips and gotchas¶
Producer-side hints with viewer_defaults¶
To make a .qvf open with the right defaults (which section to
activate, isovalue, colormap, camera bookmarks), pass
viewer_defaults= to the QVF writer or build it inside
run_job via the output-plan API. vibe-view picks up the hints
on load. See the viewer_defaults section of the user
guide.
In-memory QVF (skip the disk round-trip)¶
If you’re scripting vibe-view from a notebook and do not want a
.qvf on disk:
import io
from vibeview import launch_qvf
# Build the archive in memory.
buf = io.BytesIO()
# ... use the QVF writer with `buf` as the path ...
buf.seek(0)
launch_qvf(buf, open_browser=False)
launch_qvf accepts any seekable binary file-like, not just paths.
Remote viewing over SSH¶
For runs on a remote box you can either:
Forward the port:
ssh -L 8080:127.0.0.1:8080 remote, then runvibe-view open run.qvfon the remote and openhttp://127.0.0.1:8080in your local browser.Bind vibe-view to the public interface:
vibe-view open run.qvf --host 0.0.0.0 --no-browser. Only do this on a trusted network; the Trame server has no authentication.
The cheap alternative for SSH-only access is moltui, which renders to the terminal directly.
vibe-view says “skipped, unsupported” on a section I care about¶
The kind is not yet in vibe-view/src/vibeview/kinds.py::SUPPORTED_KINDS.
Either:
The producer wrote a kind under the
x_<vendor>.*namespace, which the viewer never tries to render by design (the namespace is reserved for producer-specific extensions).The kind is implemented on the writer but not yet on the viewer. The full matrix is in the QVF design doc § 1.4. Adding a renderer is a three-step contribution: add the kind to
SUPPORTED_KINDS, drop a renderer module invibe-view/src/vibeview/renderers/, and wire the activation branch invibe-view/src/vibeview/app.py. The existing renderers are short (~100 to ~200 lines each) and serve as templates.
What next¶
vibe-view user guide: full reference (install routes, programmatic API, every sidebar control).
QVF design: the producer / consumer format contract.
QVF consumer reference: read
.qvffiles programmatically without launching the viewer.Tutorial 27: moltui: the terminal-only sibling viewer (XSF / BXSF / Molden) for SSH contexts without browser access.
Tutorial 40: auto citations: how the
citationssection vibe-view rendered in step 3 is assembled.