Python based viewer for large multi-dimensional datasets.
After cloning this repository, you can install
python setup.py install
It requires the following dependencies:
elf(will be available via pip and conda soon)
Optionally dependencies for viewing big data:
Coming soon ;).
Coming soon ;).
Heimdall is a wrapper around
napari that makes common visualisation tasks for large volumetric data more convenient.
In particular, it supports visualizing data from
numpy arrays and
hdf5 as well as
zarr/n5 datasets and
It also supports some pyramid specifications for these file formats.
It is the easiest to use it through the convenience functions
view_arrays, which displays a list of
numpy arrays and
view_container, which displays the content of a
import numpy as np from heimdall import view_arrays shape = (128,) * 3 x = np.random.rand(*shape) y = np.random.randint(0, 1000, size=shape, dtype='uint32') # Display x as raw data and y as labels (automatically inferred from the dtypes). view_arrays([x, y])
from heimdall import view_container path = '/path/to/file.h5' # or .n5/.zarr # Display all 3d datasets in the container. # To exclude selected datasets, pass their names as list `exclude_names`. # To only show selected datasets, pass their names as list `include_names`. view_container(path, ndim=3)
view_container is also installed as command-line script.
In order to use
heimdall in a more flexible manner, use the function
It can be called with
numpy arrays as well as
z5py/h5py datasets or groups (for pyramids).
It also supports
heimdall.sources, which allow to customize the viewer further.
import numpy as np import h5py from heimdall import view, to_source shape = (128,) * 3 x = np.random.rand(*shape) path = '/path/to/file.h5' dset_name = 'some/name' with h5py.File(path, 'r') as f: ds = f[dset_name] # We wrap the h5 dataset in a source to specifiy additional options. # Here, we specify that the dataset has a channel dimension # and set the min_val and max_val that will be used for normalization by napari. y = to_source(ds, min_val=0, max_val=100, multichannel=True) # All sources need to have the same shape, otherwise `view` will fail. assert x.shape == y.shape view(x, y)
heimdall supports three different multi-scale pyramid formats:
You can load a pyramid, by passing the
h5py.Group or the corresponding knossos file to
or wrapping it into a
to_source in order to specify further options.
import h5py import z5py from heimdall import view, to_source f1 = z5py.File('/path/to/file.n5') # this needs to be a group containing an n5 pyramid pyramid1 = f1['n5-pyramid-group'] # this needs to be a bdv hdf5 file with h5py.File('/path/to/file.h5', 'r') as f2: # this is the pyramid for timepoint 0, channel 0 in the bdv format pyramid2 = f2['t00000/s00'] # we wrap it into a source to specify further options # (here: the maximum scale level to be loaded) pyramid2 = to_source(pyramid2, n_scales=3) # both pyramid data-sets need to have the same shape (at scale 0) # note that we can call shape on pyramid2 directly, because this is exposed by # the `PyramidSource` asserrt pyramid1['s0'].shape == pyramid2.shape view(pyramid1, pyramid2)
Heimdall provides several source wrappers - classes that wrap a source and
perform some tranformation on the fly.
For example, the
RoiWrapper only exposes a sub-region of the data to the viewer:
import z5py from heimdall import view, to_source from heimdall.source_wrappers import RoiWrapper # load the dataset source we want to view ds = z5py.File('/path/to/file.n5')['some/name'] # wrap it into a source (this is required in order to pass it to the wrapper) source = to_source(ds) # specify the roi (assuming this is 3d data with a matching shape!) roi_start = (0, 100, 150) roi_stop = (200, 250, 400) # wrap the source source = RoiWrapper(source, roi_start, roi_stop) print(source.shape) # (200, 150, 250) view(source)
Source wrappers can be chained.
They can also be applied to pyramids, however a
PyramidSource cannot be wrapped into
SourceWrapper directly. Instead, the
PyramidSource can be passed a factory function
factory(source, level, scale),
that needs to adjust the transformation to the individual scale level. For many source wrappers, this function is alrady implemented:
from functools import partial import z5py from heimdall import view, to_source from heimdall.source_wrappers import roi_wrapper_pyramid_factory # load the pyramid source we want to view g = z5py.File('/path/to/file.n5')['some/n5-pyramid'] # construct the wrapper factory function, # the values for `roi_start` and `roi_stop` are specified with partial roi_start = (0, 100, 150) roi_stop = (200, 250, 400) factory = partial(roi_wrapper_pyramid_factory, roi_start=roi_start, roi_stop=roi_stop) # construct the source with wrapper factory source = to_source(g, wrapper_factory=factory) view(source)
Interacting with napari
Heimdall can be combined with
napari in order to make use of additional functionality.
For this use
return_viewer=True and wrap the function call into
import numpy as np import napari from heimdall import view shape = (128,) * 3 x = np.random.rand(*shape) y = np.random.randint(0, 1000, size=shape, dtype='uint32') with napari.gui_qt(): viewer = view(x, y, return_viewer=True) # We add an additional napary points layer. points = np.array([[64, 64, 64], [32, 64, 96]]) sizes = np.array([10, 25]) viewer.add_points(points, size=sizes)
examples/ for additional usage examples.