Running vibe-qc from Jupyter Lab¶
Jupyter Lab is great for exploratory quantum-chemistry work — interactive geometry tweaks, live SCF traces, inline 3D viewers for orbitals and crystal cells, mixed code + math + prose in one document. vibe-qc works with Jupyter Lab through one of three install patterns; pick the one that matches how Jupyter is already on your system.
Decision tree¶
Your situation |
Pattern |
Effort |
|---|---|---|
No Jupyter yet, single user |
Pattern A — install Jupyter Lab into vibe-qc’s venv |
~2 min |
Jupyter Lab already installed system-wide (Homebrew / pacman / your distro’s package) |
Pattern B — register the vibe-qc venv as an |
~3 min |
JupyterHub or shared Jupyter server |
Pattern C — admin registers a kernel, or per-user |
varies |
All three patterns reach the same end-state: a Jupyter
notebook in which import vibeqc works and uses the vibe-qc
build you actually want to use.
Pattern A — Jupyter inside the vibe-qc venv¶
The simplest option: install Jupyter Lab as an extra Python
package inside the same .venv/ where vibe-qc lives. Jupyter
runs with vibe-qc on its sys.path automatically.
# From inside your vibe-qc checkout.
cd ~/path/to/vibeqc
.venv/bin/pip install jupyterlab # ~80 MB of deps; one-time
.venv/bin/jupyter lab # opens http://localhost:8888/lab
That’s the whole setup. The notebook server inherits the
venv’s Python → import vibeqc works without anything else.
Pros / cons¶
✅ One venv, one toolchain. No kernel-registration ceremony; updating vibe-qc updates the notebook environment.
✅ Works offline. No system-package dependencies.
❌ Duplicated install if you have multiple vibe-qc venvs (e.g. dev + release clones). Each needs its own Jupyter Lab.
❌ Bigger venv. Adds ~80 MB to the venv tree.
Optional: extras for richer notebooks¶
.venv/bin/pip install jupyterlab ipywidgets py3Dmol nglview matplotlib
ipywidgets— interactive controls (sliders for lattice constant sweeps, dropdowns for functional choice).py3Dmol— embedded 3D molecule / crystal viewer (the primary recommendation; see § Visualisation below).nglview— alternative viewer with crystallographic features (cell box, fractional coordinates, supercells).matplotlib— already a vibe-qc transitive dep but helpful to ensure the inline backend is registered.
Pattern B — System-wide Jupyter + vibe-qc kernel¶
If Jupyter Lab is already installed at the system or
per-user level — e.g. brew install jupyterlab on macOS,
pacman -S jupyterlab on Arch, or pipx install jupyterlab
— register the vibe-qc venv as an additional kernel.
Jupyter will offer it in the launcher.
# 1. Activate the vibe-qc venv (so ipykernel installs in it).
source ~/path/to/vibeqc/.venv/bin/activate
# 2. Install ipykernel into the vibe-qc venv (one-time):
pip install ipykernel
# 3. Register the venv as a kernel for the system Jupyter.
python -m ipykernel install --user \
--name vibeqc-dev \
--display-name "Python (vibe-qc dev)"
deactivate
Verify:
jupyter kernelspec list
# should show:
# vibeqc-dev /Users/USER/Library/Jupyter/kernels/vibeqc-dev (macOS)
# vibeqc-dev /home/USER/.local/share/jupyter/kernels/vibeqc-dev (Linux)
Launch your system Jupyter Lab — the kernel picker now offers
“Python (vibe-qc dev)” alongside whatever else you have
registered. Notebooks opened with that kernel import vibeqc from the vibe-qc venv; print(sys.executable) shows
the venv path.
Multiple vibe-qc clones (dev + release)¶
Register each as its own kernel:
source ~/vibeqc-dev/.venv/bin/activate
pip install ipykernel
python -m ipykernel install --user \
--name vibeqc-dev \
--display-name "Python (vibe-qc dev — main)"
deactivate
source ~/vibeqc-release/.venv/bin/activate
pip install ipykernel
python -m ipykernel install --user \
--name vibeqc-release \
--display-name "Python (vibe-qc release)"
deactivate
Two kernels in the launcher; pick at notebook-open time
which vibe-qc version to run against. Same logical pairing
as vq’s --branch main / --branch release.
Pros / cons¶
✅ One Jupyter Lab install serves every project.
✅ Multi-version vibe-qc without duplicating Jupyter.
✅ Updates to Jupyter Lab don’t disturb vibe-qc.
❌ Kernel needs re-registering if you delete + recreate the venv (the kernelspec’s
argvpoints at the venv’s python path; orphans causeKernelDiederrors).❌ No ipywidgets / py3Dmol unless you ALSO install them in the vibe-qc venv (the system Jupyter Lab’s installed-package set isn’t visible to your kernel’s Python).
A first vibe-qc notebook¶
Once the kernel is wired up, the smallest useful notebook:
# Cell 1 — quick sanity check
import vibeqc as vq
vq.print_banner()
Expect a 5-line banner showing the build (release vs dev, SHA, linked libraries). If it doesn’t render, you’re on the wrong kernel.
# Cell 2 — water RHF
import vibeqc as vq
mol = vq.Molecule([
vq.Atom(8, [0.0, 0.00, 0.00]),
vq.Atom(1, [0.0, 1.43, -0.98]),
vq.Atom(1, [0.0, -1.43, -0.98]),
])
basis = vq.BasisSet(mol, "6-31g*")
result = vq.run_rhf(mol, basis)
print(f"E = {result.energy_ha:.6f} Ha")
print(f"converged in {result.scf_iterations} iters")
# Cell 3 — periodic example: MgO rocksalt
import vibeqc as vq
mgo = vq.PeriodicSystem(
lattice_vectors=[[0.0, 2.106, 2.106],
[2.106, 0.0, 2.106],
[2.106, 2.106, 0.0]],
atoms=[vq.Atom(12, [0.0, 0.0, 0.0]),
vq.Atom(8, [2.106, 2.106, 2.106])],
)
basis = vq.BasisSet(mgo, "sto-3g")
result = vq.run_krhf_periodic_gdf(mgo, basis, kmesh=(1, 1, 1))
print(f"E = {result.energy_per_cell_ha:.6f} Ha/cell")
3D visualisation in notebooks¶
For inline 3D viewers, install one of:
.venv/bin/pip install py3Dmol # lightweight, recommended
.venv/bin/pip install nglview # crystal-aware; needs jupyter extension
py3Dmol — molecules and crystals¶
import py3Dmol
import vibeqc as vq
mol = vq.Molecule.from_xyz("""\
3
water
O 0.0 0.00 0.00
H 0.0 1.43 -0.98
H 0.0 -1.43 -0.98
""")
# Convert vibe-qc Molecule → XYZ string → py3Dmol view:
xyz_str = mol.to_xyz()
view = py3Dmol.view(width=400, height=300)
view.addModel(xyz_str, "xyz")
view.setStyle({"stick": {}, "sphere": {"scale": 0.3}})
view.zoomTo()
view.show()
NGLView — periodic cells¶
NGLView handles crystallographic cells well. The trick: round- trip through ASE:
import nglview
import vibeqc as vq
mgo = vq.PeriodicSystem( ... ) # as above
atoms = vq.ase.to_atoms(mgo) # vibeqc.ase → ase.Atoms
view = nglview.show_ase(atoms)
view.add_representation("ball+stick")
view.add_unitcell()
view # auto-renders in the cell
See ase_integration.md for the full
vibe-qc ↔ ASE bridge.
Watching long-running SCFs¶
vibe-qc’s ProgressLogger writes to stdout, which Jupyter
captures and re-renders per cell. Long SCFs work fine, but
note:
Per-iter output buffering can lag in Jupyter. Force flushing with
sys.stdout.flush()between iterations if the trace updates only at the end:import sys, vibeqc as vq opts = vq.RHFOptions() opts.progress = vq.ProgressLogger(flush_every=1) result = vq.run_rhf(mol, basis, opts) sys.stdout.flush()
Interrupting an SCF with the Jupyter “Interrupt Kernel” button (or
Ctrl-I,I,I) sendsKeyboardInterruptto the Python thread. The C++ side may not respond immediately for inner loops; in pathological cases (a stuck libint call) you’ll need “Restart Kernel” instead. Thevqqueue is the right tool for truly batch-shaped long runs.Working-directory effects:
run_job,run_periodic_jobwrite.out/.molden/.trajto the kernel’s current working directory — which is the notebook’s directory by default. To redirect, passoutput=:vq.run_job(mol, basis="sto-3g", method="rhf", output="./scratch/h2o") # → ./scratch/h2o.out / .molden / .traj
Or
os.chdir(...)at the top of the notebook.
OpenMP threading in notebooks¶
vibe-qc’s C++ kernels are OpenMP-parallel. The Python notebook
process inherits OMP_NUM_THREADS from its environment. If
you launched Jupyter from a shell that didn’t set
OMP_NUM_THREADS, libgomp defaults to 1 thread — your SCF
will run single-threaded and feel slow.
Two fixes:
# Option A: set in the shell before launching Jupyter:
OMP_NUM_THREADS=8 .venv/bin/jupyter lab
# Option B: set inside the notebook BEFORE importing vibeqc.
# Must come first — OpenMP reads the env var at the first
# parallel region, which is at vibeqc-module-load time.
import os
os.environ["OMP_NUM_THREADS"] = "8"
import vibeqc as vq # now uses 8 threads
If you forget and import vibe-qc with OMP_NUM_THREADS unset,
you may need to Restart Kernel before the new value takes
effect.
A future vibe-qc release will warn at import time if
OMP_NUM_THREADS is unset (a v0.8.x improvement filed by
the experimental-spikes chat).
Remote Jupyter via SSH tunnel¶
If your big-memory compute box runs Jupyter (Pattern A or B), you can drive notebooks from your laptop without exposing the Jupyter port publicly. Tunnel via SSH:
# 1. On the remote, start Jupyter bound to localhost only:
ssh remote 'OMP_NUM_THREADS=16 ~/vibeqc-dev/.venv/bin/jupyter lab \
--no-browser --port 8889 --ip 127.0.0.1'
# (prints a URL with a token in the remote terminal — copy the token)
# 2. From your laptop, tunnel port 8889 over SSH:
ssh -N -L 8889:127.0.0.1:8889 remote
# 3. Open http://localhost:8889/?token=<the-token> in your laptop browser.
# Notebooks now run on the remote's CPU + RAM + vibe-qc venv.
For workflow scale-up — same script, many parameters — use
vq submit instead. Jupyter is for interactive
exploration; vq is for batch sweeps.
Caveat list¶
Don’t
pip installfrom inside a running notebook if the package extends vibe-qc — Python’s import cache won’t pick it up until you restart the kernel. (Restart Kernel is the safe default after anypip install.)Notebook output cells can get huge with verbose SCF traces.
Cell → All Output → Clearbefore checkpointing the notebook to git; otherwise the diff is unreadable.%autoreloadworks for the Python side of vibe-qc but not for the C++ binding (_vibeqc_core.so). Native code changes require a kernel restart.%load_ext autoreload %autoreload 2 # auto-reload edits to vibeqc/*.py
GIL behaviour: vibe-qc’s C++ kernels release the GIL during long compute regions, so you can run multiple SCFs in parallel threads inside a single notebook — but that competes with OpenMP for cores. In practice, either thread-pool your Python OR use OpenMP, not both.
JupyterLab v4 vs v3 — both work. JupyterLab v4 deprecates the classic notebook server; if you see “Notebook deprecated” warnings, that’s expected and harmless.
Troubleshooting¶
Symptom |
Likely cause |
Fix |
|---|---|---|
|
wrong kernel |
check kernel picker; should say “Python (vibe-qc …)” |
Banner shows wrong vibe-qc version |
kernel points at a different venv |
re-register kernel from the right venv (Pattern B) |
SCF feels slow despite a beefy machine |
|
set it in shell or set before |
|
wrong Python (system instead of venv) |
check |
Kernel keeps dying mid-SCF |
OOM |
check the notebook’s process memory; lower |
3D viewer doesn’t render |
missing ipywidgets / py3Dmol install |
|
See also¶
running.md— running vibe-qc outside of Jupyter (venv activation, batch logs, nohup).queue.md— vq for batch-shaped sweeps; complementary to Jupyter for interactive work.ase_integration.md— vibe-qc ↔ ASE, required for NGLView crystal viewer.output_files.md— what.out/.molden/.traj/.systemfiles contain.