Use your own data#

Use this guide after you can run the supplied example. It is an adaptation checklist, not a general-purpose file importer. Keep a copy of the notebook inside the complete workshop folder and start with a small representative dataset. Keep the original files unchanged.

1. Check whether your data fit the lesson#

The workshop expects two image channels with axes in this order:

t, z, y, x

Each timepoint must have the same z,y,x shape and dtype within a channel. Frame identifiers must sort in acquisition order. A single 3D volume can be treated as one timepoint. A 2D time series uses t,y,x and needs the 2D route described below.

Do not guess axis order from the picture. Read TIFF metadata or ask the person who produced the files. A plausible-looking transposed image can still place overlays incorrectly.

2. Record units before plotting#

Write down, from acquisition metadata:

  • voxel spacing for z, y, and x, with units;

  • acquisition timestamps or the interval between frames;

  • channel names and what evidence supports their biological interpretation;

  • any crop, binning, resampling, or coordinate offset already applied.

If a value is unknown, keep spatial values in voxels and time as frame indices. Do not invent micrometres, seconds, speed, or a physical scale bar. The workshop example follows this rule because its calibration and acquisition timing are not yet confirmed.

3. Prepare tables explicitly#

A detections table must have a header with at least:

t,z,y,x

Additional columns such as amp or int may be retained as measurements, but their interpretation should be documented.

A tracks table uses:

track_id,t,z,y,x

Napari expects the identifier first. The course helper requires a headerless numeric tracks.csv in id,t,z,y,x order; it reads values with numpy.loadtxt. A file beginning with track_id,t,z,y,x will fail in that helper. For an independently written loader, a header is useful: read it with pandas and explicitly select columns in napari order. Document whether positions are array indices, source voxels, display-array coordinates, or physical coordinates.

Before display, verify that every t and spatial coordinate lies within the corresponding image bounds. Keep excluded and unmatched rows in a separate provenance record rather than silently deleting them. A track is an inferred association and should not be presented as proof of identity.

4. Use relative paths#

Keep the complete workshop folder, including its environment and source code. The copied notebook locates that root using data/zenodo-manifest.json; an unrelated folder with only a notebook is insufficient. Add your small dataset alongside the course data:

napari-workshop/
├── pyproject.toml, uv.lock, src/, scripts/
├── notebooks/my-rendering.ipynb
├── data/
│   ├── zenodo-manifest.json
│   ├── teaching/
│   └── my-data/
│       ├── metadata.json
│       ├── ch0/frame_000000.tif, frame_000001.tif, ...
│       ├── ch1/frame_000000.tif, frame_000001.tif, ...
│       ├── detections.csv
│       └── tracks.csv
└── outputs/

To reuse load_images and load_tables, both channels must contain unsigned 16-bit (uint16) ZYX stacks with these exact names and contiguous frames starting at zero. The CSV requirements above also apply. Write metadata.json to describe your arrays, for example for two unreduced volumes of shape (20, 64, 64) per channel:

{
  "spatial_factor": 1,
  "source_shape_zyx": [20, 64, 64],
  "timepoints": [0, 1],
  "coordinate_system": "source_voxels",
  "voxel_size_um": null,
  "time_step_s": null
}

Replace the shape and timepoints with measured values. A reduced dataset must record its actual reduction factor and original shape; the helper assumes the course’s sample-at-zero convention. Keep null calibration values when using source-voxel coordinates. This helper does not implement arbitrary TIFF layouts, crops, anisotropic physical scaling, or channel counts. Those need an explicitly adapted loader and layer transforms; do not change metadata merely to make an incompatible file pass.

Set the copied notebook’s data path to ROOT / "data/my-data". Relative paths allow the whole course folder to move together. Avoid a path that names one person’s Desktop or home folder.

5. Estimate image memory#

For an uncompressed in-memory array:

bytes = t × z × y × x × bytes per voxel × number of channels

uint16 uses 2 bytes per voxel. Divide bytes by 1024³ for GiB. For example, the complete workshop source images require:

30 × 118 × 664 × 860 × 2 × 2 ≈ 7.53 GiB

This excludes projections, copies, tables, Python, the operating system, and graphics memory. Do not plan to fill all available RAM. Test one timepoint first and watch actual memory on the least capable target computer.

6. Choose a loading route#

Route

Appropriate when

Main limitation

Small eager array

The full prepared array comfortably fits RAM

Loads and holds the complete array

2D or projection

The question can be answered without full depth

Projection discards depth; a slice omits other planes

Lazy source stack

Many separate source volumes are too large to hold together

Each requested chunk still takes time; displayed data still use GPU memory

Spatially reduced copy

Fine detail is not required for the teaching question

Lost detail cannot be recovered

Lazy loading and downsampling solve different problems. Downsampling after opening a compressed stack may still require reading that stack. Lazy loading does not shorten a prior download. Never call whole-series compute(), persist(), or numpy.asarray(...) on a dataset that does not fit memory.

7. Keep images and overlays aligned#

Apply coordinate transforms once. If an image was cropped, account for its source offset. If it was reduced, use the documented resampling convention. Then either transform the table coordinates or give image, points, and tracks matching layer scale and translate values.

Check several recognizable objects at early, middle, and late frames. Verify each supported reduction factor separately. A package already reduced by factor 4 can be displayed at factor 4 or coarser; it cannot recover factors 1 or 2 from absent pixels.

8. Adapt a copy of the notebook#

  1. Duplicate notebooks/01_rendering_workshop.ipynb and rename the copy.

  2. Satisfy the loader contract above, then change the data path and layer names.

  3. Adjust example indices such as z_plane = 15 and frame 10 to valid positions in your smaller dataset; update any fixed frame counts or contrast settings.

  4. Run from a restarted kernel and confirm shapes, axes, and table bounds.

  5. Add one image layer at a time, then points, then tracks.

  6. Use a new output folder for each export.

  7. Record data identity, transforms, package versions, and limitations beside the result.

Do not copy display parameters and biological captions without checking them on the new specimen. Contrast settings, particle size, tail length, and camera angle affect communication, while detection and tracking validity require their own analysis outside this workshop.

2D fallback#

For t,y,x images, omit z from points and tracks so points use t,y,x and tracks use track_id,t,y,x. For a maximum-intensity projection of 3D data, remove z only after computing the projection and document that depth was discarded. Do not leave a dummy z column and assume napari will ignore it.