# Show3DVolume – Quick Demo 3D volume viewer with interactive orthogonal slices and WebGL ray-cast volume rendering. Synthetic gold nanoparticle tomographic reconstruction with faceted shape, twin boundaries, and lattice fringes.
[1]:
# Install in Google Colab
try:
import google.colab
!pip install -q -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ quantem-widget
except ImportError:
pass # Not in Colab, skip
[2]:
try:
%load_ext autoreload
%autoreload 2
%env ANYWIDGET_HMR=1
except Exception:
pass # autoreload unavailable (Colab Python 3.12+)
env: ANYWIDGET_HMR=1
[3]:
import numpy as np
import torch
import quantem.widget
from quantem.widget import Show3DVolume
device = torch.device("mps" if torch.backends.mps.is_available() else "cuda" if torch.cuda.is_available() else "cpu")
def make_gold_nanoparticle(n=96):
"""Realistic HAADF-STEM tomographic reconstruction of a multiply-twinned gold nanoparticle."""
coords = torch.arange(n, dtype=torch.float32, device=device)
z, y, x = torch.meshgrid(coords, coords, coords, indexing="ij")
cz, cy, cx = n / 2, n / 2, n / 2
ax, ay, az = torch.abs(x - cx), torch.abs(y - cy), torch.abs(z - cz)
# Truncated octahedron shape (faceted, common for FCC gold nanoparticles)
# Blend of L1 norm (octahedron) and Linf norm (cube) → truncated octahedron
l1 = ax + ay + az
linf = torch.maximum(torch.maximum(ax, ay), az)
shape_dist = torch.maximum(l1 / 1.6, linf)
R = n * 0.37
particle = 1.0 / (1 + torch.exp((shape_dist - R) * 1.2)) # smooth boundary
# Z-contrast density: core slightly brighter (bimetallic Au@Pd-like)
r = torch.sqrt((x - cx) ** 2 + (y - cy) ** 2 + (z - cz) ** 2)
core_weight = 1.0 / (1 + torch.exp((r - R * 0.45) * 0.6))
density = 0.65 + 0.35 * core_weight
# Lattice fringes (111 planes, ~2.35 A spacing for Au)
d111 = 3.8 # spacing in voxels
fringes = 0.12 * (
torch.cos(2 * np.pi * (x + y + z) / (d111 * np.sqrt(3)))
+ 0.5 * torch.cos(2 * np.pi * (x - y + z) / (d111 * np.sqrt(3)))
)
# Twin boundary (planar mirror defect at ~54.7 deg — common five-fold twin)
twin1 = 0.18 * torch.exp(-((x - cx) * 0.707 + (y - cy) * 0.707) ** 2 / 2.0)
twin2 = 0.12 * torch.exp(-((x - cx) * 0.707 - (z - cz) * 0.707) ** 2 / 2.0)
# Stacking fault (planar defect)
sf = 0.10 * torch.exp(-((z - cz) + 0.3 * (x - cx)) ** 2 / 1.5)
volume = particle * (density + fringes + twin1 + twin2 + sf)
# Internal voids (vacancy clusters — common in real tomograms)
for dx, dy, dz, vr in [(10, -6, 4, 3.0), (-8, 8, -5, 2.5), (5, -3, -12, 2.0)]:
d = torch.sqrt((x - cx - dx) ** 2 + (y - cy - dy) ** 2 + (z - cz - dz) ** 2)
volume = volume - 0.5 * particle * torch.exp(-(d ** 2) / (2 * vr ** 2))
# Satellite particles on the surface (smaller Au clusters)
for sx, sy, sz, sr in [
(R * 0.85, 0, R * 0.5, 3.5),
(-R * 0.7, R * 0.6, 0, 2.8),
(0, -R * 0.8, -R * 0.5, 3.0),
]:
d = torch.sqrt((x - cx - sx) ** 2 + (y - cy - sy) ** 2 + (z - cz - sz) ** 2)
volume = volume + 0.8 / (1 + torch.exp((d - sr) * 2.0))
# Realistic reconstruction noise (Poisson-like — use NumPy, torch.poisson unreliable on MPS)
vol_np = volume.cpu().numpy()
vol_np += np.random.normal(0, 0.015, vol_np.shape)
vol_np = np.clip(vol_np, 0, None)
return vol_np.astype(np.float32)
volume = make_gold_nanoparticle()
print(f"Generators ready (device={device})")
Show3DVolume(volume, title="Gold Nanoparticle — Tomographic Reconstruction", cmap="inferno")
print(f"quantem.widget {quantem.widget.__version__}")
Generators ready (device=mps)
quantem.widget 0.4.0a3
Inspect Widget State#
[4]:
w = Show3DVolume(volume, title="Gold Nanoparticle", cmap="inferno")
w.summary()
Gold Nanoparticle
════════════════════════════════
Volume: 96×96×96
Slices: Z=48 Y=48 X=48
Data: min=0 max=1.645 mean=0.1681
Display: inferno | manual contrast | linear