Show2D#
One or many 2D images, including gallery panels with independent local slice stacks, plus contrast control, FFT, ROIs, line profiles, and a calibrated scale bar. See the Show2D tutorial for worked examples and Advanced Show2D for report-ready galleries, rich labels, local annotations, overlays, inset plots, and export patterns.
Reference#
Choose image size and gallery layout with plain keywords:
viewer = Show2D(images, size="medium", columns=2)
viewer.columns = 3
Use rows=2 instead to calculate columns from the number of images per page.
If both are supplied, the grid must hold every panel. size describes each
image panel: small 300, medium 450, large 600 or xlarge 900 CSS pixels.
The default remains three columns for existing notebooks. ncols still works
with a deprecation warning; do not combine it with columns or rows.
Existing saved layout state remains readable.
- class quantem.widget.show2d.Show2D(*args: t.Any, **kwargs: t.Any)#
Bases:
WatchedImageFolderMixin,Show2DExport,Show2DState,Show2DStaticPng,SavedStateMixin,HtmlExportMixin,PagesMixin,PanelsMixin,StaticFallbackMixin,AnyWidgetInteractive viewer for one 2D image or a gallery of images.
- Parameters:
data (array_like, Dataset2d, Dataset3d, or list of these) –
(H, W)for one image,(N, H, W)for a gallery,(P, N, H, W)forPpages ofNpanels. A list may mix 2D images with 3D(frames, H, W)stacks, giving that panel its own frame scrubber. Items with a trailing dimension of 3 or 4 are RGB(A) panels. A quantemDataset2d/Dataset3dsuppliessampling,unitsand the title. NumPy, PyTorch and CuPy arrays are accepted.labels (list of str, optional) – One label per panel. Entries may also be span lists (
[{"text": "a", "color": "#f00"}, {"math": r"\lambda_3"}]).page_labels (list of str, optional) – One label per page for
(P, N, H, W)input.title (str, optional) – Gallery title above the panels.
show_title (bool, optional) – Draw the title; the
ui_modepreset decides when omitted.ui_mode ({"interactive", "presentation", "report"}, default "interactive") – Preset for which controls are shown; the
show_*flags override it.cmap (str or list of str, default "inferno") – Colormap, or one per panel.
sampling (float or (row, col), optional) – Pixel size in
units; drives the scale bar and calibrated readouts.units (str, optional) – Length unit of
sampling("A","nm", …); angstrom whensamplingis given without it. Alone on a calibrated dataset it is the unit the dataset’s step is shown in.show_scale_bar (bool, optional) – Draw the scale bar.
scale_bar_position ({"bottom-right", "bottom-left"})
scale_bar_panels (list of int or str, optional) – Panels (index or label) that draw a scale bar; default all.
scale_bar_length (float, optional) – Fixed bar length in
unitsinstead of the automatic nice length.scale_bar_label (str, optional) – Fixed bar text instead of the formatted length.
scale_bar_style (dict, optional) – Bar and label styling (
font_size,color,bar_height, …).show_zoom_indicator (bool, default False) – Draw the zoom factor beside the scale bar.
show_fft (bool, optional) – Visibility of the FFT/histogram panel, the stats row, the control bar and the panel titles.
show_stats (bool, optional) – Visibility of the FFT/histogram panel, the stats row, the control bar and the panel titles.
show_controls (bool, optional) – Visibility of the FFT/histogram panel, the stats row, the control bar and the panel titles.
controls_collapsed (bool, optional) – Visibility of the FFT/histogram panel, the stats row, the control bar and the panel titles.
show_panel_titles (bool, optional) – Visibility of the FFT/histogram panel, the stats row, the control bar and the panel titles.
panel_title_spans (list, optional) – Rich title spans per panel (same schema as span labels).
panel_title_font_size (int, default 11)
panel_title_style (dict, optional) – Title badge styling (
fg,bg,align,outline_width, …).log_scale (bool, default False) – Signed-log1p display and 2/98 percentile contrast.
auto_contrast (bool, default False) – Signed-log1p display and 2/98 percentile contrast.
vmin (float or list of float, optional) – Fixed contrast window, or one per panel.
vmax (float or list of float, optional) – Fixed contrast window, or one per panel.
link_zoom (bool, optional) – Galleries link zoom and pan by default; a single image never does.
link_pan (bool, optional) – Galleries link zoom and pan by default; a single image never does.
link_contrast (bool, default True) – One shared contrast window across panels.
columns (int, optional) – Image panels across each page; three by default for compatibility. Rows are calculated automatically. For example,
columns=2places five images in three rows. Setviewer.columnsto change it later.rows (int, optional) – Desired initial rows per page; infer columns when supplied alone. If both are supplied, their capacity must hold every panel on a page.
ncols (int, optional) – Deprecated alias for
columns. Do not combine it with rows or columns.size ({"small", "medium", "large", "xlarge"}, default "medium") – Width of each image panel: 300, 450, 600 or 900 CSS pixels. Aspect ratio and source resolution are preserved; controls keep the shared font.
panel_width_px (int or None, optional) – Panel canvas width in CSS px. The medium default is 450 px per image; this changes display size only. A positive panel_width_px overrides size; 0 uses size.
smooth (bool, default False) – Bilinear instead of nearest-neighbor magnification.
zoom (float, default 1.0) – Initial zoom factor.
center ((row, col), optional) – Image point the initial view is centered on, in full-resolution pixels.
display_bin (int or "auto", default 1) – Mean-bin factor (a positive integer) of the preview sent to the browser; full-res detail streams on zoom either way. The default 1 sends native pixels. An integer above 1 bins by that factor.
"auto"picks the smallest factor that keeps the gallery under 2.5 GB of browser GPU buffers (float32 + RGBA + readback per panel) and each float32 panel under 16 MiB of initial payload. Any active bin prints one line.offline (bool, default False) – Quantize each panel to uint8 over its own range (256 levels) for a small standalone page, and print one line saying so.
panel_frame_indices (list of int, optional) – Initial frame per stack panel (negative indices count from the end).
panel_playback_fps (float, default 10) – Playback rate for stack panels.
starred (list of int or str, optional) – Panels (index or label) to star.
marker_colors (list of str, optional) – One identity color per panel, drawn as a bar (
marker_style="left") or a frame ("around").row_markers (dict, optional) –
{row_index: color}/{col_index: color}frames around gallery rows or columns.col_markers (dict, optional) –
{row_index: color}/{col_index: color}frames around gallery rows or columns.inset_plots (optional) – Per-panel inset curves, text annotations and shape overlays; the dict schema is in
show2d.optionsanddocs/api/show2d.md.panel_annotations (optional) – Per-panel inset curves, text annotations and shape overlays; the dict schema is in
show2d.optionsanddocs/api/show2d.md.panel_overlays (optional) – Per-panel inset curves, text annotations and shape overlays; the dict schema is in
show2d.optionsanddocs/api/show2d.md.panel_gap_px (optional) – Gallery chrome: the gap between panels.
inter_panel_gap_color (optional) – Gallery chrome: the gap between panels.
gallery_outer_border_px (optional) – Gallery chrome: the frame around the whole gallery.
gallery_outer_border_color (optional) – Gallery chrome: the frame around the whole gallery.
panel_inner_border_px (optional) – Gallery chrome: each panel’s own inner stroke.
panel_inner_border_color (optional) – Gallery chrome: each panel’s own inner stroke.
denoise ({"none", "gaussian", "anscombe"} or list of str, default "none") – Display-only denoise run in the browser (the data and stats stay raw); a list gives each panel its own mode. Turns the denoise switch on and shows its controls when any panel is filtered.
denoise_sigma (float or list of float, default 4.0) – Smoothing width in pixels, per panel when a list.
denoise_bin (int or list of int, default 1) – Spatial bin (1, 2 or 4) before the denoise, per panel when a list.
state (dict, str or pathlib.Path, optional) – A
state_dictor a file written bysaveto restore the view.save_state (bool, default False) – Embed the full interactive state in the saved notebook (large). The default stores a static preview plus light traits.
verbose (bool, default True) – Add the preview size to the display-bin notice (the notice itself always prints when a bin is active).
Examples
>>> from quantem.widget import Show2D >>> Show2D([raw, denoised], labels=["raw", "denoised"], sampling=0.2, units="nm", cmap="gray")
- classmethod from_folder(path: str | Path, *, pattern: str = '*', recursive: bool = False, watch: bool = True, watch_interval: float = 1.0, page_size: int | None = 20, **kwargs) Self#
Display readable folder images as a paged full-resolution gallery.
Files are ordered naturally (
image_2beforeimage_10) and read throughquantem.widget.io.read_image(), including EMD, TIFF, PNG, NPY, and DM calibration paths. The same widget is updated when stable files are added. Unreadable files remain retryable. At mostpage_sizepanels are visible at once; passNoneto keep one unpaged gallery.- Parameters:
path (str or pathlib.Path) – Folder containing independent 2D image files.
pattern (str, default "*") – Glob selecting files within
path.recursive (bool, default False) – Search matching files below subdirectories as well.
watch (bool, default True) – Start background polling immediately.
watch_interval (float, default 1.0) – Seconds between background polls.
page_size (int or None, default 20) – Maximum visible panels per page. Paging appears only after the ready image count exceeds this value. Pass
Noneto disable automatic folder paging.**kwargs – Normal
Show2Doptions. File-derived labels and data are managed by the folder source.
- property columns: int#
Image panels across each page; the saved layout uses the same value.
- set_image(data, labels: list[str | None] | None = None, *, panel_frame_indices: Sequence[int] | None = None) None#
Replace the displayed image stack without rebuilding the widget.
This updates a live image selection. It preserves display controls such as colormap, contrast, FFT/profile toggles, and gallery layout, while resetting per-panel state tied to the previous image count or dimensions.
- save_image(path: str | Path, *, idx: int | None = None, format: str | None = None, dpi: int = 150, title: bool | str = False, colorbar: bool = False, show_scale_bar: bool = False) Path#
Save current image as PNG, PDF, or TIFF.
When
title,colorbar, orshow_scale_barare enabled, the output is a publication-quality figure rendered via matplotlib. Otherwise a raw colormapped image is saved directly (faster, exact pixel output).- Parameters:
path (str or pathlib.Path) – Output file path.
idx (int, optional) – Image index in gallery mode. Defaults to current selected_idx.
format (str, optional) – ‘png’, ‘pdf’, or ‘tiff’. If omitted, inferred from file extension.
dpi (int, default 150) – Output DPI.
title (bool or str, default False) –
Trueuses the widget title, a string sets a custom title.colorbar (bool, default False) – Include a colorbar showing the intensity mapping.
show_scale_bar (bool, default False) – Include a scale bar (requires
pixel_size > 0).
- Returns:
The written file path.
- Return type:
pathlib.Path
- set_panel_frame(panel: int | str, frame: int) Self#
Set the displayed frame for one local stack panel.
Static panels have one frame and therefore only accept frame
0. Negative indices follow normal Python indexing, so-1selects the final frame (useful for Velox/EDS acquisitions whose exported HAADF is the last survey frame).
Interactive controls#
Each control mutates the listed synced trait. A UI-test agent acts on the control, then asserts the trait changed and the canvas repainted (non-zero, no console error, no NaN frame).
Control |
Trait |
Expected effect |
|---|---|---|
Colormap dropdown |
|
Canvas recolors to the chosen map |
More menu: Color shared |
|
Shared by default. Turn off to let the Color dropdown edit only the selected gallery panel; turn on for one shared colormap, then turn off again to restore the previous individual panel colormaps |
Panel identity markers |
|
Optional panel colors plus row/column group frames make panels easy to reference in notebooks, reports, and agent instructions |
Local panel annotations |
|
Optional multiple in-image labels per panel, placed by corner, normalized point, or normalized region box |
Geometric panel overlays |
|
Optional circle and rectangle overlays in data or relative coordinates, with stroke/fill opacity, dashed/dotted line styles, and z-order; More -> Overlay Edit allows live select, move, resize, delete, and reset |
Contrast min / max sliders |
|
Display clamp changes; histogram markers move |
Auto-contrast toggle |
|
Re-fits |
More menu: Contrast |
|
Applies scientist-friendly percentile ranges such as |
Log-scale toggle |
|
Intensity mapped through log |
FFT toggle |
|
Canvas shows the power spectrum; lattice spots appear |
FFT window toggle |
|
Apodization on/off (ringing at edges differs) |
FFT quality labels |
|
Compact in-panel label reports FFT sharpness, peak count, and peak SNR from the cached FFT magnitude |
FFT zoom / pan |
Browser-local per FFT panel; FFT |
Wheel or pinch zoom updates an always-visible |
Viewer chrome preset |
|
Applies shared display presets; see Viewer UI controls |
Control visibility |
|
Permanently remove controls or temporarily collapse them behind the top GUI toggle |
Title visibility |
|
Top title row shows/hides |
Stats visibility |
|
Mean/min/max/std readout shows/hides |
Panel title visibility |
|
Per-panel labels show/hide, resize, and optionally get title chrome such as background, border, and padding |
Rich panel title spans |
|
Optional structured |
Scale bar toggle |
|
Calibrated bar shows/hides (needs |
Scale bar style |
|
Restrict scale bars to selected panels and control exact publication text, font, outline, label spacing, offset, and bar thickness |
Gallery gap and borders |
|
Separately controls the layer between panels, the outside gallery frame, and each panel’s own inner stroke for browser, SVG, and static previews |
Pan (drag) |
per-image pan |
Image translates; with |
Zoom (wheel) |
|
Zooms about the cursor |
Smooth toggle |
|
Off by default: sharp data pixels (nearest neighbour); on: bilinear interpolation. The FFT panel has its own Smooth switch, also off by default |
ROI add / drag |
|
Region overlay; stats panel reports the ROI; saved notebook previews include all ROI overlays and one comparable right-side zoom crop per visible ROI; each |
Gallery select |
|
Highlights the active panel |
Local stack slider / play |
|
Every grayscale 3D list item gets independent slider/play controls; changing one panel does not move another, and constructor-configured playback speed adds no toolbar clutter |
Gallery page controls |
|
Switch, star, or play through panel pages without changing the source stack |
Panel reorder |
|
Reorders gallery display without changing source data, labels, stars, or hidden state |
Diff mode |
|
Panels render as difference vs the reference |
Link Denoise switch (gallery) |
|
Linked (“all”): denoise edits apply to every panel; unlinked (“panel”): edits apply to the selected panel only |
Denoise at construction |
|
|
Denoise master |
|
Off shows raw pixels and hides the banner without discarding method, sigma, bin, or per-panel settings |
Denoise Settings |
|
Expands/collapses the Method, sigma, and bin editor without changing whether the effect is active |
Filter master |
|
Turns frequency filtering on/off without discarding cutoff or band settings |
Filter Settings |
|
Chooses None, Low-pass, High-pass, or Band-pass and exposes the FFT-ring parameters |
More menu: Flip |
|
Display-only horizontal/vertical flips help compare orientations and point-defect neighborhoods without changing stored arrays |
More menu: Rotate |
|
Display-only 0/90/180/270° rotation for every panel or the selected panel; raw data and |
Panel inset plots |
|
Optional per-panel mini line plots for calibration curves, ACF/R sweeps, or other scientific context; hover reports the nearest plotted coordinate |
Scale bar placement |
|
Move the scale bar between bottom corners and opt into a zoom badge when a workflow needs a live magnification readout |
Rich panel labels and math#
Panel labels can be plain strings, inline math strings, or structured rich
spans. Use this for parameter sweeps where the compact panel chrome should say
λ, χ², σ, or similar symbols instead of spelling out the word.
from quantem.widget import Show2D
Show2D(
[raw, residual],
labels=[
r"$\lambda=0.03$ raw",
r"$\chi^2$/pixel residual",
],
show_stats=True,
)
The frontend renders common Greek symbols plus simple superscripts/subscripts
without requiring MathJax or KaTeX. It also normalizes doubled backslashes from
JSON/state files, so \\lambda is rendered as λ rather than as raw markup.
The same rich label path is used by panel titles, the Panels menu, the stats
row, and exported standalone HTML.
For mixed color or explicit math spans, use panel_title_spans. Each span can
contain text, math, and optional color:
Show2D(
[raw, filtered, residual],
labels=["raw", "filtered", "residual"],
panel_title_spans=[
[{"math": r"\lambda=0.03"}, {"text": " raw"}],
[{"text": "filtered", "color": "#34d399"}],
[{"math": r"\chi^2"}, {"text": "/pixel residual"}],
],
)
Use panel_annotations when the label belongs to a local region inside a panel
instead of the whole panel. An annotation can also use math or spans, so a
panel can have both a rich title and multiple local callouts:
Show2D(
[raw, residual],
panel_title_spans=[
[{"math": r"\lambda=0.03"}, {"text": " raw"}],
[{"math": r"\chi^2"}, {"text": "/pixel"}],
],
panel_annotations={
0: [
{"math": r"\lambda", "position": "top-left", "variant": "pill"},
{
"spans": [{"text": "ROI "}, {"text": "A", "color": "#60a5fa"}],
"box": [0.18, 0.25, 0.30, 0.16],
"variant": "callout",
},
],
1: {"math": r"\chi^2", "position": "top-right", "variant": "outline"},
},
)
Circle and rectangle overlays#
Use panel_overlays when the figure needs reproducible geometric callouts
in addition to analysis ROIs. Overlay coordinates use microscope image
coordinates by default: (row, col) for centers and (row0, col0, row1, col1)
for boxes. The same state is rendered in live Jupyter widgets, saved notebook
state, and standalone HTML exports.
from quantem.widget import Show2D
Show2D(
[raw, denoised, residual],
labels=["raw", "denoised", "residual"],
panel_overlays={
"raw": [
{
"shape": "circle",
"center": (96, 88),
"radius": 14,
"color": "#60a5fa",
"line_width": 3,
"line_style": "dashed",
},
{
"shape": "rect",
"box": (48, 58, 126, 146),
"color": "#facc15",
"fill_color": "#facc15",
"fill_opacity": 0.12,
"line_dash": [6, 2, 1, 2],
"z_order": 1,
},
],
"denoised": {
"shape": "rect",
"box": (75, 67, 117, 109),
"color": "#34d399",
"line_width": 2,
"line_style": "dotted",
},
},
)
Overlay strokes are solid by default. Set line_style="dashed",
line_style="dotted", or line_style="dashdot" for common scientific
callouts, or pass line_dash=[on, off, ...] for an exact canvas dash pattern.
A flat list of shapes without panel= draws each shape on every panel. Use
coords="relative" when the geometry should follow normalized panel
coordinates from 0 to 1:
Show2D(
[raw, denoised],
labels=["raw", "denoised"],
panel_overlays=[
{
"shape": "circle",
"center": (0.5, 0.5),
"radius": 0.08,
"coords": "relative",
"color": "#f87171",
}
],
)
The live widget and exported HTML also expose More -> Overlay Edit when
overlays are present. In edit mode, click a circle or rectangle to select it,
drag inside to move it, drag an edge to resize it, press Delete to remove the
selected overlay, and choose Reset Overlays to restore the constructor state.
Use ROIs when the shape should drive statistics, FFT crops, or Python
readback through roi_list.
Presentation and export chrome#
ui_mode="presentation" starts with controls collapsed so the scientific image
gets the first view. It still leaves a compact Controls button for adjusting
the widget and an Export button for saving the current standalone HTML:
w = Show2D(
[raw, residual],
labels=[r"$\lambda=0.03$ raw", r"$\chi^2$/pixel"],
ui_mode="presentation",
show_stats=True,
)
w.export_html("lambda_sweep.html", encoding="uint8")
In live Jupyter, the Export menu can request exact or uint8 standalone HTML through the Python backend. In standalone HTML, the Export button downloads the current embedded page using the representation already present in that file.
For Illustrator or Inkscape, use the Export menu’s SVG item or call
w.export_svg(...). Show2D writes a hybrid publication SVG: measured image
panels remain embedded rasters, while panel titles, annotations, geometric
overlays, inset plots, scale bars, colorbars, and group markers are editable
SVG objects that match the current figure state.
Publication SVG typography and layout keys#
Use these keys when Show2D should produce a publication figure that can go
directly to Illustrator or Inkscape.
Panel title fonts#
labels set the panel title text. panel_title_font_size sets the size, and
panel_title_style controls typography and placement:
PUBLICATION_FONT = (
"Nimbus Sans, Helvetica, Arial, "
"Liberation Sans, DejaVu Sans, sans-serif"
)
Show2D(
panels,
labels=["a 0° scan", "b 90° scan", "c combined"],
panel_title_font_size=16,
panel_title_style={
"font_family": PUBLICATION_FONT,
"font_weight": 700,
"fg": "#ffffff",
"outline_color": "#000000",
"outline_width": 2.2,
"x": 0.035,
"y": 0.035,
"anchor": "top-left",
"align": "left",
},
)
To match a published PDF, inspect its embedded fonts and put the matching family first:
pdffonts path/to/published_figure.pdf
fc-match "Helvetica"
If the PDF text was outlined or rasterized, no editable text font may be reported; use the source figure script or the closest installed Helvetica-like family instead.
Accepted panel_title_style keys:
Key |
Meaning |
|---|---|
|
CSS/SVG font-family stack, for example |
|
Numeric or named weight, for example |
|
Text fill color |
|
Text stroke used for publication contrast |
|
Relative panel coordinates from 0 to 1 |
|
|
|
Pixel nudge |
|
Text alignment fallback when |
|
Optional title chrome |
Local annotation fonts#
Use panel_annotations for multiple labels inside the same image panel. Each
annotation can have its own font, color, outline, and position:
Show2D(
panels,
labels=["f composite on 0° HAADF"],
panel_annotations={
"f composite on 0° HAADF": [
{
"text": "Ba+Ti",
"x": 0.20,
"y": 0.15,
"anchor": "center",
"align": "center",
"font_family": PUBLICATION_FONT,
"font_size": 15,
"font_weight": 800,
"color": "#ff4dff",
"outline_color": "#000000",
"outline_width": 1.8,
"variant": "plain",
},
{
"text": "Sr",
"x": 0.80,
"y": 0.15,
"anchor": "center",
"align": "center",
"font_family": PUBLICATION_FONT,
"font_size": 15,
"font_weight": 800,
"color": "#58ff58",
"outline_color": "#000000",
"outline_width": 1.8,
"variant": "plain",
},
],
},
)
Use x and y to attach a label to a physical region of the panel. Use
box=[left, top, width, height] when the label describes an area. Use
variant="plain" for text-only publication labels, or badge, pill,
outline, and callout for report-style labels.
Scale bar fonts and placement#
scale_bar_panels limits the bar to one or more panels. Values can be panel
indices or label strings. scale_bar_length is in the physical unit implied by
sampling and units; scale_bar_label overrides the displayed text.
Show2D(
panels,
labels=labels,
sampling=0.0105,
units="nm",
scale_bar_panels=["f corrected combined"],
scale_bar_length=2.0,
scale_bar_label="2 nm",
scale_bar_style={
"font_family": PUBLICATION_FONT,
"font_size": 16,
"font_weight": 700,
"color": "#ffffff",
"outline_color": "#000000",
"outline_width": 1.3,
"bar_height": 5,
"label_gap": 5,
"offset": (0, -8),
},
show_zoom_indicator=False,
)
Accepted scale_bar_style keys:
Key |
Meaning |
|---|---|
|
Scale-bar label typography |
|
Bar and label fill color |
|
Label text stroke |
|
Fallback label shadow when no outline is used; also opts into a small scale-bar shadow |
|
Bar thickness in SVG/browser CSS pixels |
|
Pixels between label baseline and bar |
|
Pixel nudge |
Pixel-perfect gutters#
Use explicit gallery chrome controls for manuscript grids:
Show2D(
panels,
labels=labels,
columns=3,
panel_gap_px=2,
inter_panel_gap_color="#000000",
gallery_outer_border_px=2,
gallery_outer_border_color="#000000",
panel_inner_border_px=1,
panel_inner_border_color="#000000",
)
panel_gap_px and inter_panel_gap_color control only the layer between panels.
gallery_outer_border_* controls the frame around the whole grid.
panel_inner_border_* controls the stroke drawn inside each image panel.
Which denoise filter should I use?#
The Denoise controls are hidden behind their own toggle by default; everything here is display-only (the stored array, the stats row, and raw exports keep the original counts, and an active denoise always announces itself with a one-line banner). Three methods cover the space and binning is a separate knob: for a binned Poisson smooth pick Poisson (Anscombe) and set Bin 2.
Your data |
Use |
Why |
|---|---|---|
Sparse EDS / counting maps |
Poisson (Anscombe), Bin 2, sigma 6-10 |
Respects Poisson count statistics; the standard choice for element maps |
Very sparse maps (single counts) |
Poisson (Anscombe), Bin 4, sigma 8-12 |
More SNR from binning before smoothing |
HAADF / decent-dose images |
Gaussian, Bin 1, sigma 1-2 (or nothing) |
The data is not count-starved; a light smooth is enough |
Anything quantitative (FFT, intensities, stats) |
None |
Measure on raw counts; the stats row is always computed from raw data |
From Python, the same ladder is denoise="anscombe", denoise_bin=2, denoise_sigma=8 (per-panel lists supported for A/B galleries).
Reuse ROI coordinates in notebooks and agents#
ROIs are synced in roi_list and saved in state_dict(). Each entry is a dict
with the shape ("circle", "square", "rectangle" or "annular"), the
center row and col, and the size (radius, radius_inner for an annulus,
width and height for a rectangle) in full-resolution pixels. Set the list
from Python to place ROIs, and read it back after drawing them in the browser:
w = Show2D(img)
w.roi_list = [{
"shape": "circle", "row": 72, "col": 65, "radius": 12, "radius_inner": 6,
"width": 24, "height": 24, "color": "#4fc3f7", "line_width": 2, "highlight": False,
}]
w.roi_active = True
roi = w.roi_list[0]
roi["row"], roi["col"], roi["radius"] # (72, 65, 12)
Save and restore a view#
state_dict() returns the display state (ROIs, selected panel, hidden panels,
panel order, local stack frames, contrast, colormap, FFT, denoise and filter,
zoom and scale-bar settings) without the image data. save(path) writes it to
a file, and the state= argument restores it on a new widget over the same
images:
w = Show2D([raw, corrected, residual], labels=["raw", "corrected", "residual"])
w.show_fft = True
w.save("defect_a.json")
Show2D([raw, corrected, residual], state="defect_a.json")
The file is {"schema": "quantem.widget-state/2", "widget_name", "widget_version", "state"}, the same for every widget with save. A file of another schema
(or of an earlier release, which has none) and a state key the widget does not
save raise ValueError before anything is applied; an earlier file is not
converted.
Add scientific inset plots to panels#
Advanced figure-making sometimes needs a compact plot inside each image panel:
for example an autocorrelation score versus an R ratio while reviewing
automatic denoising calibration. Use inset_plots for that per-panel context.
The top-level parameter stays singular and readable, while each dictionary keeps
the plot data, placement, labels, and style together.
Show2D(
denoised_panels,
labels=["candidate A", "candidate B", "candidate C"],
inset_plots=[
{
"x": r_values,
"y": acf_values_for_panel,
"point": (best_r, best_acf),
"xlabel": "R",
"ylabel": "ACF",
"legend": "ACF/R",
"annotation": f"R*={best_r:.2f}",
"position": "bottom-right",
"margin": 24,
"size": 0.36,
"height": 0.26,
"show_ticks": True,
"xticks": [0, 1],
"yticks": [0, 1],
"line_width": 2.6,
"background_alpha": 0.58,
"border_width": 0,
}
for acf_values_for_panel, best_r, best_acf in calibration_results
],
scale_bar_position="bottom-left",
show_zoom_indicator=False,
)
For normal notebooks, prefer position plus margin, size, and height.
Use box=[left, top, width, height] only when a publication figure needs exact
normalized panel coordinates. border_width=0 gives a clean no-frame look;
increase background_alpha or use a subtle border_color when the underlying
image is noisy. On hover, the live widget reports the nearest plotted
coordinate using the axis labels, such as R 0.465 · ACF 0.48.
If inset_plots is present, the live widget shows an Inset Chart switch in
the More menu. A scientist can hide the chart during image inspection, turn
it back on for reporting, or drag the chart inside the panel. Dragging previews
freely and then snaps to the closest corner on release, updating position and
margin in the widget state.
Remove a background or isolate a periodicity#
Frequency Filter is deliberately separate from Denoise. Denoise promises a cleaner view of the measurement; High-pass and Band-pass deliberately remove real signal, so their displayed pixels must not be treated as measurable raw counts. The stored array, statistics row, and raw exports remain unchanged.
# Flatten a slow brightness gradient.
Show2D(eds_map, show_fft=True,
frequency_filter="highpass", frequency_filter_cutoff=0.08)
# Isolate a lattice-frequency ring.
Show2D(lattice, show_fft=True,
frequency_filter="bandpass",
frequency_filter_center=0.32,
frequency_filter_width=0.08)
Parameters are fractions of Nyquist from 0 to 1. Drag the cyan FFT ring to select the cutoff or band center by eye. The FFT overlay dims rejected frequencies: Low-pass keeps the clear area inside the ring, High-pass keeps the clear area outside, and Band-pass keeps only the clear annulus. Filter and its More-menu toggle are off by default; turning the master on with no remembered mode starts with Low-pass. Denoise and Filter are chainable in the fixed order Denoise then Filter; each active operation has its own banner. Turn the Filter master off or choose None to restore the unfiltered view without losing the settings.
For paged galleries, FFT work is demand-driven: only panels visible on the current page are transformed. Visiting another page computes that page once and retains the bounded cache for later return visits.
FFT quality labels#
Pass show_fft=True to show the FFT panel. By default, fft_metrics=True
adds a small white label inside each FFT panel with three quick checks:
sharpness, peak count, and peak SNR. These values are computed from the FFT
magnitude already used for rendering, so the label does not trigger a second
FFT. Set fft_metrics=False when a clean FFT image is more important than the
readout.
The first FFT for an image, local panel frame, ROI, or window configuration may take a moment on large data. After that, Show2D reuses that bounded cache entry for redraws, zoom/pan, contrast changes, metric labels, and return visits to the same slice. During a first-time slice computation, the previous valid FFT stays visible instead of flashing to a dark loading panel.
Each interactive FFT panel also carries its own bottom-left zoom multiplier.
It starts at 2.0×, follows wheel and touch-pinch zoom immediately, and returns
to 2.0× on double-click, double-tap, or Reset. In a gallery, unlinked FFTs
report independent values; enabling FFT Link Zoom makes their values move
together without changing the real-space zoom.
Reorder gallery panels#
panel_order reorders the gallery display without changing the source data,
labels, stars or hidden state:
w = Show2D(images, labels=["raw", "filtered", "residual"])
w.panel_order = [2, 0, 1] # residual, raw, filtered
w.panel_order = [] # the natural order again
Live image updates#
Use set_image() to trigger a new browser render in an already displayed
Show2D widget. Keep a reference to the widget object, display it once, then
replace the image or gallery data through that method:
import numpy as np
from quantem.widget import Show2D
w = Show2D(first_image, labels=["initial"])
w
for step, next_image in enumerate(image_stream, start=1):
w.set_image(next_image, labels=[f"step {step}"])
For a gallery, pass a 3D stack (N, H, W) and one label per panel:
w.set_image(
np.stack([raw, filtered, residual]),
labels=["raw", "filtered", "residual"],
)
Independent local stack panels#
A bare 3D array still means a static gallery of N images. To give gallery
panels their own frame or slice axes, pass a Python list whose 3D items are each
shaped (frames, rows, cols). Every grayscale 3D list item becomes one panel
with its own slider, play/pause control, frame count, and current frame. Counts
may differ between panels. RGB(A) list items keep the color-image behavior
described in the constructor reference.
This is useful for tomography or multislice studies that produce several reconstruction volumes. The scientist can keep four methods, regularization settings, or slice thicknesses side by side, stop each one at the depth where a feature or artifact is clearest, and retain linked spatial context without forcing all panels onto one global slice index:
from quantem.widget import Show2D
reconstructions = [
recon_8_slices_20A,
recon_16_slices_10A,
recon_regularized,
recon_alternative,
]
w = Show2D(
reconstructions,
labels=[
"8 slices x 20 A",
"16 slices x 10 A",
"regularized",
"alternative",
],
panel_frame_indices=[3, 7, -1, 0],
panel_playback_fps=4,
columns=2,
link_zoom=True,
link_pan=True,
)
w.set_panel_frame("16 slices x 10 A", 8)
w
Use a list even when all reconstructions happen to have the same slice count; the outer list is what declares independent local stacks. Use Show3D instead when all panels should advance together on one global frame or slice axis.
The list may also mix stack panels with ordinary 2D images:
w = Show2D(
[eds_sum_map, haadf_stack, ti_map, o_map],
labels=["EDS sum", "HAADF", "Ti", "O"],
panel_frame_indices=[0, -1, 0, 0],
columns=2,
auto_contrast=True,
)
w
Only the HAADF panel gets an in-panel slider and play button. Each local frame
index remains keyed to its source panel when panels are hidden or reordered.
Click a stack panel and use the left or right arrow key to scrub it. From
Python, use w.set_panel_frame("HAADF", -1).
Set panel_playback_fps when constructing the widget to choose the cadence for
all local-stack play buttons without adding another compact control. The
default is 10 fps; values above the 30 fps browser budget are capped. The
setting is saved in widget state and carried into standalone HTML exports,
while the per-panel playing/paused state remains browser-local so reopening a
report does not start playback unexpectedly.
The active panel’s histogram, stats, and FFT follow its current local frame;
scrubbing it does not change neighboring panels. state_dict() records
panel_frame_indices, and single HTML exports using either encoding="full"
or encoding="uint8" contain every local frame. For an interactively restored
notebook output, construct with save_state=True; the default
save_state=False deliberately stores only a compact static preview rather
than embedding the stack payload in the notebook.
For single-image ROI review, that compact saved-notebook preview keeps the scientific marks visible: the fallback PNG draws every visible ROI on the full image and adds one right-side zoom crop per ROI. The zoom crops use a common crop size where image boundaries allow it, so multiple ROIs remain visually comparable. A reader who opens the notebook or report without rerunning the cell can still see the marked features.
set_image() accepts the same mixed list form:
w.set_image(
[next_eds_map, next_haadf_stack, next_ti_map, next_o_map],
labels=["EDS sum", "HAADF", "Ti", "O"],
panel_frame_indices=[0, 0, 0, 0],
)
Watch a growing image folder#
Use Show2D.from_folder(...) when a microscope or reconstruction job writes
new 2D images into one folder. Each newly readable file becomes another panel
in the existing gallery. The widget object is not rebuilt, so the current
selection and the state of panels already present remain stable.
from quantem.widget import Show2D
w = Show2D.from_folder(
"/data/session/haadf",
pattern="*.tif",
watch_interval=2.0,
page_size=20,
title="Live HAADF images",
)
w
watch=True is the default. Pass watch=False for a fixed folder or a
reproducible script that should update only when you call poll_folder().
Folder galleries default to page_size=20: page controls appear automatically
when the 21st ready image arrives. Use another positive integer to change the
visible limit, or page_size=None to keep one unpaged gallery. The final page
contains only real files, so 45 images form pages of 20, 20, and 5 panels.
Folder pages keep selection, stars, hidden state, and ordering keyed to each
source file rather than sharing a hidden slot across pages.
To change the grouping, open the folder again with another page_size.
Paging limits the panels, histograms, and FFT views rendered at one time. The current folder implementation still retains the complete full-resolution gallery in Python and transports its display previews to the browser; it is not yet a lazy, bounded-memory source-page cache. Open a smaller file selection when the complete gallery exceeds available memory.
An empty watched folder remains mounted with a waiting view and becomes the
real gallery in the same widget model when its first stable file arrives.
The compact title-area badge reports Watching, Updating, Waiting for file completion, Watch error, or Stopped; fixed watch=False snapshots do not
show the badge.
new_panels = w.poll_folder() # scan now; return newly appended indices
w.stop_folder_watch() # pause background scans
w.watch_folder(interval=1.0) # resume with a different interval
w.close() # stop watching and close the widget
Folder watching is append-only. A file already represented in the gallery is not duplicated, an incomplete file is deferred until a later poll, and removing or rewriting a source file does not silently remove or replace an existing panel. An incompatible shape is reported without blocking a later compatible file. Close long-running widgets when the notebook no longer needs them.
Show2D.from_folder(...) reads the scientific image data at its source
resolution.
To verify the live path, add genuine EMD files after the widget is visibly mounted and check that the same browser canvas paints each full-resolution panel.
Paged galleries#
Direct Show2D(...) pages are comparison pages. Use them when each view
contains the same panel grid across several
analysis settings, iterations, or parameter values. A common example is a
4-by-4 reconstruction sweep where each page is one iteration or one denoising
parameter, and the panels within the page are the related output images.
These repeated-slot comparison pages are distinct from the sequential item
pages created by Show2D.from_folder(..., page_size=20).
Pass a 4D array with shape (pages, panels_per_page, rows, cols):
from quantem.widget import Show2D
w = Show2D(
reconstruction_sweep,
labels=[
"lambda 0.01", "lambda 0.03", "lambda 0.10", "lambda 0.30",
"lambda 1", "lambda 3", "lambda 10", "lambda 30",
"raw", "filtered", "residual", "score",
"phase", "amplitude", "mask", "diagnostic",
],
page_labels=["iteration 10", "iteration 20", "iteration 30"],
columns=4,
)
w
You can also pass explicit page dictionaries when the page titles naturally belong beside the image data:
w = Show2D(
[
{"title": "iteration 10", "images": iter10_panels, "labels": panel_labels},
{"title": "iteration 20", "images": iter20_panels, "labels": panel_labels},
],
columns=4,
)
Paged galleries keep the Python data model simple: all pages use the same panel
count and image shape, the browser renders only the active page, and page stars
are stored separately from panel stars. Use star_page(page) from Python
(page_starred holds one 0/1 flag per page, so assigning it clears a star),
or the star button beside the page slider in the widget. The page row also includes play/pause and a small FPS menu so
readers can step through iteration or parameter pages without touching the main
image controls. Manual slider scrubbing pauses page playback. For very large 4K
sweeps, start with a reduced or representative stack; a future lazy page
transport can avoid sending every page to the browser at once.
set_image() is the re-render trigger. Mutating the original NumPy array in
place does not notify the frontend. The method sends fresh synced frame_bytes
and resets state tied to the old image count or dimensions, including stale
hidden panels, stars, view box, ROIs, line profiles, detail tiles, and panel
order. Each new frame reaches the browser over the live Jupyter connection;
offline=True would only quantize the panels to uint8.