HTML and file export#

Open in Colab

View or download this notebook on GitHub.

Most sharing should use interactive HTML: one browser file that opens without a Python kernel and keeps the widget controls live. When collaborators need to keep working in Python, share the saved notebook with its widget state instead.

Need

Best format

Why

Receiver opens

Share a finished interactive view

Interactive HTML

One portable browser file, no Python kernel

.html in a browser

Continue the analysis together

Saved notebook with widget state

Keeps code, outputs, and widget state together

.ipynb in JupyterLab or VS Code

Put an image in a paper or slide

PNG figure

Static, compact, easy to cite

.png

Put a time series in slides or email

GIF or MP4 animation

Plays without widget JavaScript

.gif or .mp4

Reopen the same widget settings later

JSON view state

Small settings file for Python workflows

.json

Send a complete report package

ZIP bundle

Groups HTML, figures, and state files

.zip

This page uses the same real gold HAADF moving-crop stack as the Show3D tutorial, so the export examples match the data users see elsewhere in the docs. It follows the common order: HTML first, notebook sharing second, then smaller supporting exports.

import os, pathlib, tempfile

os.environ.setdefault("HF_HUB_DISABLE_PROGRESS_BARS", "1")

from quantem.widget import Show2D, Show3D
from quantem.widget.data import load_tutorial_show3d

out = pathlib.Path(tempfile.mkdtemp(prefix="quantem_widget_share_"))

# Real gold HAADF moving-crop stack used by the Show3D tutorial.
volume_dataset = load_tutorial_show3d(n_frames=32, stride=8, crop_size=256, verbose=False)
first_frame = volume_dataset.array[0]
image_sampling = volume_dataset.sampling[1:]
image_units = volume_dataset.units[1:]
volume_dataset.array.shape, first_frame.shape
((32, 256, 256), (256, 256))

1. Export interactive HTML#

Use HTML when someone should open the result in a browser and still scrub, zoom, change contrast, or use the widget controls. This is usually the best default for sharing a finished interactive view.

Show3D and Show3DSlices can write a single self-contained HTML file that keeps the scrub interactive with no kernel. Two common encodings are:

  • exact (default): embeds float32 bytes and preserves numerical precision.

  • encoded uint8: embeds a compact display pack plus global min/max - much smaller, and visually identical after the colormap for most sharing.

In the widget below, click Export to download the current interactive HTML file to your local device. Use that downloaded .html file when you want to share the interactive gold HAADF stack directly.

show3d = Show3D(volume_dataset, offline=True, panel_width_px=520)
exact = show3d.export_html(out / 'gold_haadf_exact.html')
quant = show3d.export_html(out / 'gold_haadf_uint8.html', quantized=True)
for p in (exact, quant):
    print(f'{p.name:24s} {p.stat().st_size/1e6:6.2f} MB')

# The same widget state is what the exported HTML opens in a browser.
show3d
gold_haadf_exact.html     12.15 MB
gold_haadf_uint8.html      3.76 MB

2. Export an animation for slides or email#

Use GIF when someone should see the movie in PowerPoint, Keynote, email, or a static report. MP4 is still available when a video file is required, but GIF is the easiest slide path. This is different from HTML: the animation plays anywhere, but the receiver cannot keep zooming, panning, or changing contrast.

The widget Export menu first asks for the format: GIF, Interactive HTML, or secondary MP4 video. The GIF panel exposes frame range, maximum frame count, fps, spatial size, and estimated render size before compression. The Slides preset sets a slide-friendly starting point: at most 40 frames with a 512 px panel edge.

For notebooks or scripted reports, use Python when you need the same presentation-specific options from code:

show3d.save_gif("gold_movie_slides.gif", quality="medium", fps=8, slides_preset=True)
show3d.save_gif("gold_movie.gif", quality="medium", fps=6, frame_start=0, frame_stop=24, max_frames=12, max_edge_px=768)
show3d.save_mp4("gold_movie.mp4", quality="high", fps=12, max_frames=40)

For large movies, run the maintainer smoke report in dry-run mode before exporting all qualities:

PYTHONPATH=src:. python scripts/widget_show3d_animation_smoke.py \
  --artifact-dir /tmp/quantem-widget-show3d-gif-dry-run \
  --dry-run

3. Share the notebook with widget state#

Use the notebook when collaborators should rerun cells, edit analysis code, or continue the work in JupyterLab or VS Code. Interact with the widgets, save the notebook, and share the .ipynb with any needed data files.

Open analysis.ipynb in JupyterLab or VS Code, interact with the widgets, then save the notebook.

A saved widget notebook contains two pieces: a widget output in the cell and metadata.widgets at the notebook level. Opening that notebook in a compatible Jupyter frontend reuses the saved state, so the receiver sees the same widget view before rerunning anything.

Warning

Jupyter trust matters. In end-to-end tests with Show2D and Show3D, untrusted copied notebooks kept the saved widget metadata but showed a plain text widget summary instead of the interactive canvas. Trust a notebook only when you know the source, or rerun the cells yourself. After trust, the saved widget state restores in JupyterLab.

For ShowEDS, small exact-data cubes can reopen from the notebook alone; large ShowEDS.from_emd(...) notebooks also need the referenced data folder beside the notebook.

GitHub’s native notebook preview is different: it does not run widget JavaScript. Use the documentation site, Colab, Jupyter, or quantem html when you want interaction. Only make a GitHub-preview copy when you deliberately want static pictures in GitHub’s .ipynb renderer.

cp analysis.ipynb analysis_github.ipynb
quantem github analysis_github.ipynb --no-execute

4. Save a reusable widget view#

save() writes a small, versioned JSON file capturing the current view: colormap, contrast, ROIs, zoom, and related widget settings. Use this when you want to restore the same view inside Python later, not as the primary sharing format.

show2d = Show2D(
    first_frame,
    cmap="magma",
    sampling=image_sampling,
    units=image_units,
    title="Gold HAADF frame",
    offline=True,
)
state_path = show2d.save(str(out / "gold_haadf_view.json"))
state_path = out / "gold_haadf_view.json"
print("state:", state_path.name, "-", state_path.stat().st_size, "bytes")
state: gold_haadf_view.json - 3791 bytes

5. Save a figure#

save_image() writes the colormapped image directly, or a publication-style figure with a title, colorbar, and scale bar when you ask for them. Use this for static figures, not interactive sharing.

png_path = show2d.save_image(out / 'gold_haadf_frame.png', scalebar=True, colorbar=True, title='Gold HAADF frame')
print('figure:', png_path.name, '-', png_path.stat().st_size, 'bytes')
figure: gold_haadf_frame.png - 628888 bytes

6. Export Show2D SVG for Illustrator#

Use the Show2D Export menu and choose SVG. The export keeps panel frames, marker bars, panel labels, scale bars, geometric overlays, local annotations, inset plots, group markers, and colorbars as editable SVG objects. The scientific image panels stay as embedded PNG images inside the SVG, because measured pixel data is not vectorized. SVG export uses a high-resolution embedded image scale by default; from Python, pass a smaller scale only when file size matters.

From Python, call export_svg() on the current widget state.

svg_path = show2d.export_svg(out / 'gold_haadf_figure.svg', include_scale_bar=True)
print('svg:', svg_path.name, '-', svg_path.stat().st_size, 'bytes')
svg: gold_haadf_figure.svg - 296633 bytes

7. Bundle shared files#

Exported HTML, PNG, and JSON state files are ordinary files. If a collaborator needs several of them together, bundle them with the standard library.

import zipfile
bundle = out / 'widget_report.zip'
with zipfile.ZipFile(bundle, 'w', zipfile.ZIP_DEFLATED) as zf:
    for p in [state_path, png_path, exact, quant]:
        zf.write(p, arcname=p.name)
print('bundle:', bundle.name, '-', bundle.stat().st_size/1e6, 'MB')
print('contains:', zipfile.ZipFile(bundle).namelist())
bundle: widget_report.zip - 8.159951 MB
contains: ['gold_haadf_view.json', 'gold_haadf_frame.png', 'gold_haadf_exact.html', 'gold_haadf_uint8.html']

Tip

For embedding a widget in these docs (or any nbconvert/Jupyter Book page), construct it with offline=True and let the notebook bake the state - the same mechanism export_html uses, but inline in the page.