Comparing reconstructions#

Open in Colab

A Show2D panel does not have to be a single image: any list item that is a 3D array becomes a panel with its own local frame stack, scrubbed independently of its neighbors. Panels can mix 2D and 3D items, and stacks can have different frame counts.

Why this matters in practice:

  • Regularization sweeps - one panel per λ, each panel scrubbing that λ’s iterations, so over-smoothing vs. noise is visible side by side.

  • Convergence checks - scrub one reconstruction through its iterations while a reference stays fixed in the next panel.

  • Slice comparisons - multislice ptychography reconstructions with different slice counts still compare cleanly, because each panel owns its stack length.

  • Denoise / parameter studies - same field of view, one panel per setting.

This tutorial uses the reconstruction snapshots for the synthetic Ducky example from the public bobleesj/quantem-data Hugging Face dataset - the same run whose loss curves Show1D monitors. Here we look at the reconstructions themselves.

Tip

Run this exact notebook with the Colab badge above, or View or download this notebook on GitHub. For finished results, use HTML and file export to export interactive HTML or share a trusted notebook with widget state.

Ducky simulation tutorial: Georgios Varnavides, Trademark ducky dataset (October 23, 2025). The viewer files contain subsequent reconstruction results for the synthetic example.

import quantem.widget as qw
qw.profile()

import numpy as np

from quantem.widget.datasets import show1d_ducky

run = show1d_ducky(verbose=False)
snapshots = run / "snapshots"
sorted(p.name for p in snapshots.glob("lambda_3_*.npy"))[:4]
quantem.widget  0.0.1rc44.dev0
  install       editable checkout
  commit        2d009a7f61ee (dirty checkout)
quantem.gpu     0.0.1rc18.dev0
  install       local build
  commit        not recorded
quantem         0.1.10
  install       installed package
  commit        not recorded
webgpu kernels  fa4a86c (fa4a86cfee85), pinned fa4a86cfee85ea719be2dd98206d2098f0dd3344
torch           2.14.1+cu130  device=cpu
python          3.12.15
['lambda_3_f000.npy',
 'lambda_3_f001.npy',
 'lambda_3_f002.npy',
 'lambda_3_f003.npy']

One panel per λ, iterations as local frames#

Each regularization value saved 12 snapshots during the run. Stack each λ’s snapshots into a 3D array and pass the list to Show2D: every panel gets its own frame slider (every third iteration here keeps the docs page light - drop the [::3] to scrub all 12):

from quantem.widget import Show2D

lambdas = ["0p3", "3", "30", "300"]


def iterations(tag):
    files = sorted(snapshots.glob(f"lambda_{tag}_f*.npy"))
    return np.stack([np.load(f) for f in files[::3]])


Show2D(
    [iterations(tag) for tag in lambdas],
    labels=[f"lambda {tag.replace('p', '.')}" for tag in lambdas],
    title="Synthetic Ducky reconstructions (tutorial: Georgios Varnavides)",
)

Scrub any panel: too little regularization stays noisy through every iteration, too much washes out the lattice. The winner is obvious visually in a way a loss curve alone does not show.

Mixing a fixed reference with scrubbed stacks#

A 2D item renders as a static panel next to the 3D stacks, so the ground-truth reference can sit beside the reconstructions it judges:

reference = np.load(snapshots / "reference.npy")

Show2D(
    [reference, iterations("0p3"), iterations("30")],
    labels=["reference", "lambda 0.3", "lambda 30"],
    title="Ducky reference vs. reconstructions (tutorial: Georgios Varnavides)",
)

The stacks keep their own lengths - a 4-frame sweep and a 12-frame sweep compare fine - which is exactly what you need when reconstructions with different slice counts or iteration budgets end up in the same figure.