Skip to content

Commit

Permalink
adding a export to yt method
Browse files Browse the repository at this point in the history
  • Loading branch information
chrishavlin committed Nov 21, 2024
1 parent b0a1d3b commit e3c8b90
Show file tree
Hide file tree
Showing 2 changed files with 428 additions and 0 deletions.
318 changes: 318 additions & 0 deletions docs/examples/ytnapari_to_yt.ipynb

Large diffs are not rendered by default.

110 changes: 110 additions & 0 deletions src/yt_napari/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
from typing import Any, List, Optional, Set, Tuple, Union

import numpy as np
import yt
from napari import Viewer
from napari.components.layerlist import LayerList
from napari.layers import Layer
from napari.layers.utils._link_layers import get_linked_layers
from unyt import unyt_array, unyt_quantity
from yt.data_objects.static_output import Dataset as ytDataset

import yt_napari._model_ingestor as _mi
from yt_napari.logging import ytnapari_log
Expand Down Expand Up @@ -617,3 +619,111 @@ def get_data_range(
max_val = max([max_val, layer.data.max()])

return (min_val, max_val)


def layers_to_yt(
viewer: Viewer,
layers: Optional[List[Union[str, int]]] = None,
bbox: Optional[np.ndarray] = None,
**kwargs,
) -> ytDataset:
"""
Load layers from the napari viewer as a yt uniformg grid dataset.
Parameters
----------
viewer: napari.Viewer
the active napari Viewer instance
layers: List[str, int]
optional list of layers to load. If not supplied, will attempt
to use all available layers.
bbox: np.ndarray
optional bounding box array
kwargs
any additional keyword arguments are passed to yt.load_uniform_grid
Returns
-------
Dataset
a yt dataset
Notes
-----
Current limitations:
* Multi-level data is not currently supported
* Selected layers must all have the same shape (and extent)
* Data is copied
"""

available_layers = viewer.layers
available_layer_names = [layer.name for layer in available_layers]
available_layer_ids = range(0, len(available_layers))
if layers is None:

Check warning on line 663 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L660-L663

Added lines #L660 - L663 were not covered by tests
# try to load them all
layers = available_layer_names

Check warning on line 665 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L665

Added line #L665 was not covered by tests

# some validation
layer_shape = available_layers[layers[0]].data.shape

Check warning on line 668 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L668

Added line #L668 was not covered by tests
# ndim = available_layers[layers[0]].ndim # use below...
for layer in layers:
if isinstance(layer, int) and layer not in available_layer_ids:
msg = (

Check warning on line 672 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L670-L672

Added lines #L670 - L672 were not covered by tests
f"Layer {layer} not found in valid range of layer ids: "
f"{available_layer_ids}."
)
raise RuntimeError(msg)
elif isinstance(layer, str) and layer not in available_layers:
msg = (

Check warning on line 678 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L676-L678

Added lines #L676 - L678 were not covered by tests
f"Layer {layer} not found in list of available layers: "
f"{available_layer_names}."
)
raise RuntimeError(msg)
elif not isinstance(layer, str) and not isinstance(layer, int):
msg = (

Check warning on line 684 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L682-L684

Added lines #L682 - L684 were not covered by tests
f"Unexpected layer type, type({layer})={type(layer)} but it "
f" must be a str or int."
)
raise TypeError(msg)

Check warning on line 688 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L688

Added line #L688 was not covered by tests

active_layer = available_layers[layer]
if layer_shape != active_layer.data.shape:
msg = (

Check warning on line 692 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L690-L692

Added lines #L690 - L692 were not covered by tests
"Can only export layers as a yt dataset if they have "
f"the same dimensions. {layers[0]} has shape of {layer_shape},"
f" while {layer} has shape { active_layer.data.shape}"
)
raise RuntimeError(msg)

Check warning on line 697 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L697

Added line #L697 was not covered by tests

# first go: just copy the data.
# note: not using layer for name directly, because it could be an integer
# index or
data = {

Check warning on line 702 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L702

Added line #L702 was not covered by tests
available_layers[layer].name: available_layers[layer].data for layer in layers
}

# TODO: check dimensionality (2D layers)

# TODO: check for multi-level and just load the finest level?
# layer.level_shapes is a list of shapes for each level

# TODO: axis order? common for bio images to be ordered z, y, x...
# is there metadata for that?

if bbox is None:
bbox = np.array([[0.0, 1.0], [0.0, 1.0], [0.0, 1.0]])

Check warning on line 715 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L714-L715

Added lines #L714 - L715 were not covered by tests
# TODO: layers have an extent attribute, looks like, e.g.,:
# Extent(data=array([[ 0., 0., 0.],
# [ 16., 512., 512.]]), world=array([[-5.000e-01, -5.000e-01, -5.000e-01],
# [ 1.550e+01, 5.115e+02, 5.115e+02]]), step=array([1., 1., 1.]))
# that world array could be used as a bounding box.

if "length_unit" in kwargs:
lu = kwargs.pop("length_unit")

Check warning on line 723 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L722-L723

Added lines #L722 - L723 were not covered by tests
else:
lu = 1.0

Check warning on line 725 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L725

Added line #L725 was not covered by tests

ds = yt.load_uniform_grid(data, layer_shape, bbox=bbox, length_unit=lu, **kwargs)

Check warning on line 727 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L727

Added line #L727 was not covered by tests

return ds

Check warning on line 729 in src/yt_napari/viewer.py

View check run for this annotation

Codecov / codecov/patch

src/yt_napari/viewer.py#L729

Added line #L729 was not covered by tests

0 comments on commit e3c8b90

Please sign in to comment.