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 real joint-time ptychography lambda sweep from the public bobleesj/quantem-data Hugging Face dataset - the same run the Show1D tutorial monitors as loss curves. 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.

import numpy as np

from quantem.widget.datasets import show1d_ducky

run = show1d_ducky(size="small", verbose=False)
snapshots = run / "snapshots"
sorted(p.name for p in snapshots.glob("lambda_3_*.npy"))[:4]
['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="Ducky lambda sweep - scrub each panel's iterations",
)

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="Reference vs. reconstructions",
)

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.