From 8fb49c48e7728b55cf28943442833fbbdfb007ed Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Mon, 28 Oct 2024 11:12:57 -0600 Subject: [PATCH 01/39] feat(xarray): porting pyvista-xarray to pure vtk --- .codespellrc | 2 +- pan3d/xarray/__init__.py | 5 + pan3d/xarray/__source.py | 290 +++++++++++++++++++++++++++++++++ pan3d/xarray/accessor.py | 98 +++++++++++ pan3d/xarray/datasets.py | 194 ++++++++++++++++++++++ pan3d/xarray/errors.py | 2 + pan3d/xarray/io.py | 135 +++++++++++++++ pan3d/xarray/vtk_data_model.py | 30 ++++ pyproject.toml | 9 + tests/__init__.py | 0 tests/conftest.py | 17 ++ tests/data/air_temperature.vtr | 25 +++ tests/data/structured.vts | 27 +++ tests/data/wavelet.vti | 14 ++ tests/test_builder.py | 12 +- tests/test_xarray.py | 151 +++++++++++++++++ 16 files changed, 1004 insertions(+), 7 deletions(-) create mode 100644 pan3d/xarray/__init__.py create mode 100644 pan3d/xarray/__source.py create mode 100644 pan3d/xarray/accessor.py create mode 100644 pan3d/xarray/datasets.py create mode 100644 pan3d/xarray/errors.py create mode 100644 pan3d/xarray/io.py create mode 100644 pan3d/xarray/vtk_data_model.py create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/data/air_temperature.vtr create mode 100644 tests/data/structured.vts create mode 100644 tests/data/wavelet.vti create mode 100644 tests/test_xarray.py diff --git a/.codespellrc b/.codespellrc index c6a15b93..5c5ba3b5 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,2 +1,2 @@ [codespell] -skip = CHANGELOG.md +skip = CHANGELOG.md,tests/data/* diff --git a/pan3d/xarray/__init__.py b/pan3d/xarray/__init__.py new file mode 100644 index 00000000..a24ed782 --- /dev/null +++ b/pan3d/xarray/__init__.py @@ -0,0 +1,5 @@ +import pan3d.xarray.accessor # noqa +from vtkmodules import register_vtk_module_dependencies + + +register_vtk_module_dependencies("vtkCommonDataModel", "pan3d.xarray.vtk_data_model") diff --git a/pan3d/xarray/__source.py b/pan3d/xarray/__source.py new file mode 100644 index 00000000..85c2f667 --- /dev/null +++ b/pan3d/xarray/__source.py @@ -0,0 +1,290 @@ +import traceback +from typing import List, Optional + +import numpy as np +import pyvista as pv +from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase +import xarray as xr + + +class BaseSource(VTKPythonAlgorithmBase): + def __init__(self, nOutputPorts=1, outputType="vtkTable", **kwargs): + VTKPythonAlgorithmBase.__init__( + self, + nInputPorts=0, + nOutputPorts=nOutputPorts, + outputType=outputType, + **kwargs, + ) + + def GetOutput(self, port=0): + output = pv.wrap(self.GetOutputDataObject(port)) + if output.active_scalars is None and output.n_arrays: + if len(output.point_data): + output.set_active_scalars(output.point_data.keys()[0]) + elif len(output.cell_data): + output.set_active_scalars(output.cell_data.keys()[0]) + return output + + def apply(self): + self.Update() + return self.GetOutput() + + def update(self): + """Alias for self.Update()""" + return self.Update() + + def get_output(self, port=0): + """Alias for self.GetOutput()""" + return self.GetOutput(port=port) + + +class PyVistaXarraySource(BaseSource): + def __init__( + self, + data_array: Optional[xr.DataArray] = None, + x: Optional[str] = None, + y: Optional[str] = None, + z: Optional[str] = None, + time: Optional[str] = None, + order: str = "C", + component: Optional[str] = None, + mesh_type: Optional[str] = None, + resolution: Optional[float] = None, + ): + BaseSource.__init__( + self, + nOutputPorts=1, + outputType="vtkRectilinearGrid", + ) + self._data_array = data_array + self._resolution = resolution + + self._x = x + self._y = y + self._z = z + self._order = order + self._component = component + self._mesh_type = mesh_type + + self._time = None + self._time_index = 0 + if isinstance(time, str): + self._time = time + elif time is not None: + raise TypeError + + self._z_index = None + self._slicing = None + self._sliced_data_array = None + self._persisted_data = None + self._mesh = None + + def __str__(self): + return f""" +data_array: {self._data_array} +resolution: {self._resolution} +x: {self._x} +y: {self._y} +z: {self._z} +order: {self._order} +component: {self._component} +time: {self._time} +time_index: {self._time_index} +""" + + @property + def data_array(self): + return self._data_array + + @data_array.setter + def data_array(self, data_array): + self._data_array = data_array + self.Modified() + + @property + def resolution(self): + return self._resolution + + @resolution.setter + def resolution(self, resolution: int): + self._resolution = resolution + self.Modified() + + @property + def x(self): + return self._x + + @x.setter + def x(self, x: str): + self._x = x + self.Modified() + + @property + def y(self): + return self._y + + @y.setter + def y(self, y: str): + self._y = y + self.Modified() + + @property + def z(self): + return self._z + + @z.setter + def z(self, z: str): + self._z = z + self.Modified() + + @property + def time(self): + return self._time + + @time.setter + def time(self, time: str): + self._time = time + self.Modified() + + @property + def order(self): + return self._order + + @order.setter + def order(self, order: str): + self._order = order + self.Modified() + + @property + def component(self): + return self._component + + @component.setter + def component(self, component: str): + self._component = component + self.Modified() + + @property + def time_index(self): + return self._time_index + + @time_index.setter + def time_index(self, time_index: int): + self._time_index = time_index + self.Modified() + + @property + def max_time_index(self): + if self._time: + return len(self.data_array[self._time]) - 1 + + @property + def z_index(self): + return self._z_index + + @z_index.setter + def z_index(self, z_index: int): + self._z_index = z_index + self.Modified() + + @property + def slicing(self): + return self._slicing + + @slicing.setter + def slicing(self, slicing: Optional[List[int]]): + self._slicing = slicing + self.Modified() + + @property + def sliced_data_array(self): + if self._sliced_data_array is None: + self._compute_sliced_data_array() + return self._sliced_data_array + + @property + def persisted_data(self): + if self._persisted_data is None: + self._persisted_data = self.sliced_data_array.persist() + return self._persisted_data + + @property + def mesh(self): + if self._mesh is None: + self._compute_mesh() + return self._mesh + + @property + def data_range(self): + da = self.persisted_data + return da.min(), da.max() + + def resolution_to_sampling_rate(self, data_array): + """Convert percentage to sampling rate.""" + shape = np.array(data_array.shape) + n = np.floor(shape * self._resolution) + rate = np.ceil(shape / n).astype(int) + return np.pad(rate, (0, 3 - len(rate)), mode="constant") + + def _compute_sliced_data_array(self): + if self.data_array is None: + self._sliced_data_array = None + return None + + indexing = {} + if self._slicing is not None: + indexing = { + k: slice(*v) + for k, v in self._slicing.items() + if k in [self.x, self.y, self.z] + } + + if self._time is not None: + indexing.update(**{self._time: self.time_index}) + + if self.z and self.z_index is not None: + indexing.update(**{self.z: self.z_index}) + + da = self.data_array.isel(indexing) + + if self._slicing is None and self._resolution is not None: + rx, ry, rz = self.resolution_to_sampling_rate(da) + if da.ndim <= 1: + da = da[::rx] + elif da.ndim == 2: + da = da[::rx, ::ry] + elif da.ndim == 3: + da = da[::rx, ::ry, ::rz] + + self._sliced_data_array = da + return self._sliced_data_array + + def _compute_mesh(self): + self._mesh = self.persisted_data.pyvista.mesh( + x=self._x, + y=self._y, + z=self._z if self._z_index is None else None, + order=self._order, + component=self._component, + mesh_type=self._mesh_type, + scales={k: v[2] for k, v in self._slicing.items()} if self._slicing else {}, + ) + return self._mesh + + def Modified(self, **kwargs): + self._sliced_data_array = None + self._persisted_data = None + self._mesh = None + super().Modified(**kwargs) + + def RequestData(self, request, inInfo, outInfo): + # Use open data_array handle to fetch data at + # desired Level of Detail + try: + pdo = self.GetOutputData(outInfo, 0) + pdo.ShallowCopy(self.mesh) + except Exception as e: + traceback.print_exc() + raise e + return 1 diff --git a/pan3d/xarray/accessor.py b/pan3d/xarray/accessor.py new file mode 100644 index 00000000..9b846579 --- /dev/null +++ b/pan3d/xarray/accessor.py @@ -0,0 +1,98 @@ +from typing import Dict, Optional + +import numpy as np +import xarray as xr + +from vtkmodules.vtkCommonDataModel import vtkDataSet +from pan3d.xarray import datasets + +# from pvxarray.vtk_source import PyVistaXarraySource + + +class _LocIndexer: + def __init__(self, parent: "VTKAccessor"): + self.parent = parent + + def __getitem__(self, key) -> xr.DataArray: + return self.parent._xarray.loc[key] + + def __setitem__(self, key, value) -> None: + self.parent._xarray.__setitem__(self, key, value) + + +@xr.register_dataarray_accessor("vtk") +class VTKAccessor: + def __init__(self, xarray_obj: xr.DataArray): + self._xarray = xarray_obj + + def __getitem__(self, key): + return self._xarray.__getitem__(key) + + @property + def data(self): + return self._xarray.values + + @property + def loc(self) -> _LocIndexer: + """Attribute for location based indexing like pandas.""" + return _LocIndexer(self) + + def _get_array(self, key, scale=1): + try: + values = self._xarray[key].values + if "float" not in str(values.dtype) and "int" not in str(values.dtype): + # non-numeric coordinate, assign array of scaled indices + values = np.array(range(len(values))) * scale + + return values + except KeyError: + raise KeyError( + f"Key {key} not present in DataArray. Choices are: {list(self._xarray.coords.keys())}" + ) + + def dataset( + self, + x: Optional[str] = None, + y: Optional[str] = None, + z: Optional[str] = None, + order: Optional[str] = None, + component: Optional[str] = None, + mesh_type: Optional[str] = None, + scales: Optional[Dict] = None, + ) -> vtkDataSet: + if mesh_type is None: # Try to guess mesh type + max_ndim = max( + *[self._get_array(n).ndim for n in (x, y, z) if n is not None] + ) + mesh_type = "structured" if max_ndim > 1 else "rectilinear" + + try: + builder = getattr(datasets, mesh_type) + except KeyError: + raise KeyError + return builder( + self, x=x, y=y, z=z, order=order, component=component, scales=scales + ) + + # def algorithm( + # self, + # x: Optional[str] = None, + # y: Optional[str] = None, + # z: Optional[str] = None, + # time: Optional[str] = None, + # order: str = "C", + # component: Optional[str] = None, + # mesh_type: Optional[str] = None, + # resolution: float = 1.0, + # ): + # return PyVistaXarraySource( + # data_array=self._xarray, + # x=x, + # y=y, + # z=z, + # time=time, + # order=order, + # component=component, + # mesh_type=mesh_type, + # resolution=resolution, + # ) diff --git a/pan3d/xarray/datasets.py b/pan3d/xarray/datasets.py new file mode 100644 index 00000000..f1f4d9bf --- /dev/null +++ b/pan3d/xarray/datasets.py @@ -0,0 +1,194 @@ +from typing import Dict, Optional + +import numpy as np +import warnings +from pan3d.xarray.errors import DataCopyWarning +from vtkmodules.vtkCommonDataModel import vtkRectilinearGrid, vtkStructuredGrid + + +def imagedata_to_rectilinear(image_data): + output = vtkRectilinearGrid() + output.SetDimensions(image_data.dimensions) + origin = image_data.origin + spacing = image_data.spacing + extent = image_data.extent + coords = [] + for axis in range(3): + coords.append( + np.array( + [ + origin[axis] + (spacing[axis] * i) + for i in range(extent[axis * 2], extent[axis * 2 + 1] + 1) + ], + dtype=np.double, + ) + ) + + output.x_coordinates, output.y_coordinates, output.z_coordinates = coords + output.point_data.ShallowCopy(image_data.point_data) + output.cell_data.ShallowCopy(image_data.cell_data) + output.field_data.ShallowCopy(image_data.field_data) + + return output + + +def _coerce_shapes(*arrs): + """Coerce all argument arrays to have the same shape.""" + maxi = 0 + ndim = 0 + for i, arr in enumerate(arrs): + if arr is None: + continue + if arr.ndim > ndim: + ndim = arr.ndim + maxi = i + # print(arrs) + # if ndim != len(arrs) - (*arrs,).count(None): + # print(ndim, len(arrs)) + # raise ValueError + if ndim < 1: + raise ValueError + shape = arrs[maxi].shape + reshaped = [] + for arr in arrs: + if arr is not None and arr.shape != shape: + if arr.ndim < ndim: + arr = np.repeat([arr], shape[2 - maxi], axis=2 - maxi) + else: + raise ValueError + reshaped.append(arr) + return reshaped + + +def _points( + accessor, + x: Optional[str] = None, + y: Optional[str] = None, + z: Optional[str] = None, + order: Optional[str] = "F", + scales: Optional[Dict] = None, +): + """Generate structured points as new array.""" + if order is None: + order = "F" + ndim = 3 - (x, y, z).count(None) + if ndim < 2: + if ndim == 1: + raise ValueError( + "One dimensional structured grids should be rectilinear grids." + ) + raise ValueError("You must specify at least two dimensions as X, Y, or Z.") + if x is not None: + x = accessor._get_array(x, scale=(scales and scales.get(x)) or 1) + if y is not None: + y = accessor._get_array(y, scale=(scales and scales.get(y)) or 1) + if z is not None: + z = accessor._get_array(z, scale=(scales and scales.get(z)) or 1) + arrs = _coerce_shapes(x, y, z) + x, y, z = arrs + arr = [a for a in arrs if a is not None][0] + points = np.zeros((arr.size, 3), dtype=arr.dtype) + if x is not None: + points[:, 0] = x.ravel(order=order) + if y is not None: + points[:, 1] = y.ravel(order=order) + if z is not None: + points[:, 2] = z.ravel(order=order) + shape = list(x.shape) + [1] * (3 - ndim) + return points, shape + + +def rectilinear( + accessor, + x: Optional[str] = None, + y: Optional[str] = None, + z: Optional[str] = None, + order: Optional[str] = "C", + component: Optional[str] = None, + scales: Optional[Dict] = None, +): + if scales is None: + scales = {} + + ndim = 3 - (x, y, z).count(None) + if ndim < 1: + raise ValueError("You must specify at least one dimension as X, Y, or Z.") + + # Build dataset + dataset = vtkRectilinearGrid() + + if x is not None: + dataset.x_coordinates = accessor._get_array(x, scale=scales.get(x, 1)) + if y is not None: + dataset.y_coordinates = accessor._get_array(y, scale=scales.get(y, 1)) + if z is not None: + dataset.z_coordinates = accessor._get_array(z, scale=scales.get(z, 1)) + + # Update grid size + dataset.dimensions = [ + dataset.x_coordinates.size, + dataset.y_coordinates.size, + dataset.z_coordinates.size, + ] + + # Handle field + values = accessor.data + values_dim = values.ndim + if component is not None: + # if ndim < values.ndim and values.ndim == ndim + 1: + # Assuming additional component array + dims = set(accessor._xarray.dims) + dims.discard(component) + print("values changed - transpose") + values = accessor._xarray.transpose( + *dims, component, transpose_coords=True + ).values + values = values.reshape((-1, values.shape[-1]), order=order) + warnings.warn( + DataCopyWarning( + "Made a copy of the multicomponent array - VTK/PyVista data not shared with xarray." + ) + ) + ndim += 1 + else: + print("values changed - ravel") + values = values.ravel(order=order) + + # Validate dimensions of field + if values_dim != ndim: + msg = f"Dimensional mismatch between specified X, Y, Z coords and dimensionality of DataArray ({ndim} vs {values_dim})" + if ndim > values_dim: + raise ValueError( + f"{msg}. Too many coordinate dimensions specified leave out Y and/or Z." + ) + raise ValueError( + f"{msg}. Too few coordinate dimensions specified. Be sure to specify Y and/or Z or reduce the dimensionality of the DataArray by indexing along non-spatial coordinates like Time." + ) + + array_name = str(accessor._xarray.name or "data") + dataset.point_data[array_name] = values + return dataset + + +def structured( + accessor, + x: Optional[str] = None, + y: Optional[str] = None, + z: Optional[str] = None, + order: Optional[str] = "F", + component: Optional[str] = None, + scales: Optional[Dict] = None, +): + if scales is None: + scales = {} + + points, shape = _points(accessor, x=x, y=y, z=z, order=order, scales=scales) + + print(f"{shape=}") + dataset = vtkStructuredGrid(points=points) + dataset.SetDimensions(shape) + dataset.point_data[accessor._xarray.name or "data"] = accessor.data.ravel( + order=order + ) + + return dataset diff --git a/pan3d/xarray/errors.py b/pan3d/xarray/errors.py new file mode 100644 index 00000000..9580902a --- /dev/null +++ b/pan3d/xarray/errors.py @@ -0,0 +1,2 @@ +class DataCopyWarning(Warning): + pass diff --git a/pan3d/xarray/io.py b/pan3d/xarray/io.py new file mode 100644 index 00000000..20c5028f --- /dev/null +++ b/pan3d/xarray/io.py @@ -0,0 +1,135 @@ +from pathlib import Path +import warnings + +import numpy as np +import xarray as xr +from xarray.backends import BackendEntrypoint + +from pvxarray.errors import DataCopyWarning + +from vtkmodules.vtkIOXML import ( + vtkXMLImageDataReader, + vtkXMLRectilinearGridReader, + vtkXMLStructuredGridReader, +) +from vtkmodules.vtkIOLegacy import vtkDataSetReader +from vtkmodules.vtkCommonDataModel import vtkDataObject + +READERS = { + ".vti": vtkXMLImageDataReader, + ".vtr": vtkXMLRectilinearGridReader, + ".vts": vtkXMLStructuredGridReader, + ".vtk": vtkDataSetReader, +} + + +def read(file_path): + reader = READERS[Path(file_path).suffix](file_name=file_path) + # reader.SetFileName(file_path) + return reader() + + +def rectilinear_grid_to_dataset(mesh): + dims = list(mesh.dimensions) + dims = dims[-1:] + dims[:-1] + return xr.Dataset( + { + name: (["z", "x", "y"], mesh.point_data[name].ravel().reshape(dims)) + for name in mesh.point_data.keys() + }, + coords={ + "x": (["x"], mesh.x_coordinates), + "y": (["y"], mesh.y_coordinates), + "z": (["z"], mesh.z_coordinates), + }, + ) + + +def image_data_to_dataset(mesh): + origin = mesh.origin + spacing = mesh.spacing + extent = mesh.extent + + def gen_coords(i): + return np.array( + [ + origin[i] + (spacing[i] * v) + for v in range(extent[i * 2], extent[i * 2 + 1] + 1) + ], + dtype=np.double, + ) + + dims = list(mesh.dimensions) + return xr.Dataset( + { + name: (["z", "x", "y"], mesh.point_data[name].ravel().reshape(dims)) + for name in mesh.point_data.keys() + }, + coords={ + "x": (["x"], gen_coords(0)), + "y": (["y"], gen_coords(1)), + "z": (["z"], gen_coords(2)), + }, + ) + + +def structured_grid_to_dataset(mesh): + warnings.warn( + DataCopyWarning( + "StructuredGrid dataset engine duplicates data - VTK data not shared with xarray." + ) + ) + + return xr.Dataset( + { + name: ( + ["xi", "yi", "zi"], + mesh.point_data[name].ravel().reshape(mesh.dimensions), + ) + for name in mesh.point_data.keys() + }, + coords={ + "x": (["xi", "yi", "zi"], mesh.x_coordinates), + "y": (["xi", "yi", "zi"], mesh.y_coordinates), + "z": (["xi", "yi", "zi"], mesh.z_coordinates), + }, + ) + + +DATASET_TO_XARRAY = { + "vtkRectilinearGrid": rectilinear_grid_to_dataset, + "vtkImageData": image_data_to_dataset, + "vtkStructuredGrid": structured_grid_to_dataset, +} + + +def dataset_to_xarray(dataset): + if isinstance(dataset, vtkDataObject): + for ds_type in DATASET_TO_XARRAY: + if dataset.IsA(ds_type): + return DATASET_TO_XARRAY[ds_type](dataset) + + raise TypeError( + f"pan3d is unable to generate an xarray DataSet from the {type(dataset)} VTK data type at this time." + ) + + +class VTKBackendEntrypoint(BackendEntrypoint): + def open_dataset( + self, + filename_or_obj, + *, + drop_variables=None, + ): + return dataset_to_xarray(read(filename_or_obj)) + + open_dataset_parameters = [ + "filename_or_obj", + "attrs", + ] + + def guess_can_open(self, filename_or_obj): + try: + return Path(filename_or_obj).suffix in READERS + except TypeError: + return False diff --git a/pan3d/xarray/vtk_data_model.py b/pan3d/xarray/vtk_data_model.py new file mode 100644 index 00000000..fe308062 --- /dev/null +++ b/pan3d/xarray/vtk_data_model.py @@ -0,0 +1,30 @@ +r""" +Module that extend VTK data_model until available mainstream +""" + +from vtkmodules.util.data_model import PointSet +from vtkmodules.vtkCommonDataModel import ( + vtkStructuredGrid, +) + + +@vtkStructuredGrid.override +class vtkStructuredGrid(PointSet, vtkStructuredGrid): + @property + def dimensions(self): + # handle deprecation + dims = [0, 0, 0] + self.GetDimensions(dims) + return dims + + @property + def x_coordinates(self): + return self.points[:, 0].reshape(self.dimensions, order="F") + + @property + def y_coordinates(self): + return self.points[:, 1].reshape(self.dimensions, order="F") + + @property + def z_coordinates(self): + return self.points[:, 2].reshape(self.dimensions, order="F") diff --git a/pyproject.toml b/pyproject.toml index 0e9c75a2..a99d87ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,6 +74,15 @@ slice-explorer = "pan3d.explorers.slice_explorer:main" requires = ['setuptools', 'wheel'] build-backend = 'setuptools.build_meta' +[project.entry-points."xarray.backends"] +vtk = "pan3d.xarray.io:VTKBackendEntrypoint" + +[tool.pytest.ini_options] +filterwarnings = [ + "ignore::pan3d.xarray.errors.DataCopyWarning", +] + + [tool.setuptools.packages.find] where = ["."] diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..598cd89b --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,17 @@ +import pytest +from pathlib import Path + + +@pytest.fixture(scope="session") +def vtr_path(): + return str((Path(__file__).with_name("data") / "air_temperature.vtr").resolve()) + + +@pytest.fixture(scope="session") +def vts_path(): + return str((Path(__file__).with_name("data") / "structured.vts").resolve()) + + +@pytest.fixture(scope="session") +def vti_path(): + return str((Path(__file__).with_name("data") / "wavelet.vti").resolve()) diff --git a/tests/data/air_temperature.vtr b/tests/data/air_temperature.vtr new file mode 100644 index 00000000..f32800b4 --- /dev/null +++ b/tests/data/air_temperature.vtr @@ -0,0 +1,25 @@ + + + + + + + AQAAAACAAAC0FAAAbwkAAA==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 + + + + + + + AQAAAACAAADUAAAAfgAAAA==eJwNyFkGAlAAQNG3tHg/iUQikUgkEolEojRo0KBBgwYN2kdL63xd54aQjGGQiiGkNaNZzWleC1rUkpa1olWtaV0b2tSWtrWjXe1pP4bfQIcxJEbemCc85RnPecFLXvGaN7zlHe/5wEc+8ZkvfOUb3/nBT37xmz/8jX96xji2 + + + AQAAAACAAABkAAAASAAAAA==eJwNwyESQFAUAMA3sizLsmzmS7Isy7KoKL8oskM4hEM4hCPYndmIs484zO5uri7OTo4OdrY21laWFn4p4vXx9jK7pB9G9BEy + + + AQAAAACAAAAIAAAACwAAAA==eJxjYIAAAAAIAAE= + + + + + diff --git a/tests/data/structured.vts b/tests/data/structured.vts new file mode 100644 index 00000000..8c185776 --- /dev/null +++ b/tests/data/structured.vts @@ -0,0 +1,27 @@ + + + + + + + AQAAAACAAAAAZAAA7hsAAA==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 + + + 0 + + + 14.177446008 + + + + + + + diff --git a/tests/data/wavelet.vti b/tests/data/wavelet.vti new file mode 100644 index 00000000..3d4d9aa1 --- /dev/null +++ b/tests/data/wavelet.vti @@ -0,0 +1,14 @@ + + + + + + + AgAAAACAAAC0EAAAX0MAAOUOAAA=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 + + + + + + + diff --git a/tests/test_builder.py b/tests/test_builder.py index 4083e799..e1560e41 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -200,9 +200,9 @@ def test_setters_invalid_values(): ) -def test_import_error(): - # This will only succeed in an environment where - # pan3d is installed but pan3d[geotrame] is not installed. - builder = DatasetBuilder() - with pytest.raises(ImportError): - builder.viewer +# def test_import_error(): +# # This will only succeed in an environment where +# # pan3d is installed but pan3d[geotrame] is not installed. +# builder = DatasetBuilder() +# with pytest.raises(ImportError): +# builder.viewer diff --git a/tests/test_xarray.py b/tests/test_xarray.py new file mode 100644 index 00000000..a65720a2 --- /dev/null +++ b/tests/test_xarray.py @@ -0,0 +1,151 @@ +import numpy as np +import xarray as xr +from pan3d.xarray.io import dataset_to_xarray, read as vtk_read +from pan3d.xarray.datasets import imagedata_to_rectilinear + + +def compare_ds(a, b, *attrs): + for attr in attrs: + if hasattr(a, attr): + assert np.array_equal( + getattr(a, attr), getattr(b, attr) + ), f"Not matching {attr}" + elif attr in a.point_data.keys(): + assert np.array_equal( + a.point_data[attr], b.point_data[attr] + ), f"Not matching point_data[{attr}]" + elif attr in a.cell_data.keys(): + assert np.array_equal( + a.cell_data[attr], b.cell_data[attr] + ), f"Not matching cell_data[{attr}]" + else: + assert False, f"Missing attribute {attr}" + + +def test_engine_is_available(): + assert "vtk" in xr.backends.list_engines() + + +def test_read_vtr(vtr_path): + ds = xr.open_dataset(vtr_path, engine="vtk") + truth = vtk_read(vtr_path) + assert np.allclose(ds["air"].values.ravel(), truth.point_data["air"].ravel()) + assert np.allclose(ds["x"].values, truth.x_coordinates) + assert np.allclose(ds["y"].values, truth.y_coordinates) + assert np.allclose(ds["z"].values, truth.z_coordinates) + accessor_ds = ds["air"].vtk.dataset(x="x", y="y", z="z") + compare_ds( + accessor_ds, + truth, + "x_coordinates", + "y_coordinates", + "z_coordinates", + "air", + ) + + +def test_read_vti(vti_path): + ds = xr.open_dataset(vti_path, engine="vtk") + truth = vtk_read(vti_path) + truth_r = imagedata_to_rectilinear(truth) + assert np.allclose(ds["RTData"].values.ravel(), truth.point_data["RTData"].ravel()) + assert np.allclose(ds["x"].values, truth_r.x_coordinates) + assert np.allclose(ds["y"].values, truth_r.y_coordinates) + assert np.allclose(ds["z"].values, truth_r.z_coordinates) + compare_ds( + ds["RTData"].vtk.dataset(x="x", y="y", z="z"), + truth_r, + "x_coordinates", + "y_coordinates", + "z_coordinates", + "RTData", + ) + + +def test_read_vts(vts_path): + ds = xr.open_dataset(vts_path, engine="vtk") + truth = vtk_read(vts_path) + assert np.allclose( + ds["Elevation"].values.ravel(), truth.point_data["Elevation"].ravel() + ) + assert np.allclose(ds["x"].values, truth.x_coordinates) + assert np.allclose(ds["y"].values, truth.y_coordinates) + assert np.allclose(ds["z"].values, truth.z_coordinates) + accessor_ds = ds["Elevation"].vtk.dataset(x="x", y="y", z="z") + compare_ds( + accessor_ds, + truth, + "x_coordinates", + "y_coordinates", + "z_coordinates", + "Elevation", + ) + + +def test_convert_vtr(vtr_path): + truth = vtk_read(vtr_path) + ds = dataset_to_xarray(truth) + mesh = ds["air"].vtk.dataset(x="x", y="y", z="z") + assert np.array_equal(ds["air"].values.ravel(), truth.point_data["air"].ravel()) + assert np.may_share_memory( + ds["air"].values.ravel(), truth.point_data["air"].ravel() + ) + assert np.array_equal(mesh.x_coordinates, truth.x_coordinates) + assert np.array_equal(mesh.y_coordinates, truth.y_coordinates) + assert np.array_equal(mesh.z_coordinates, truth.z_coordinates) + assert np.may_share_memory(mesh.z_coordinates, truth.z_coordinates) + compare_ds( + mesh, + truth, + "x_coordinates", + "y_coordinates", + "z_coordinates", + "air", + ) + + +def test_convert_vti(vti_path): + truth = vtk_read(vti_path) + ds = dataset_to_xarray(truth) + truth_r = imagedata_to_rectilinear(truth) + mesh = ds["RTData"].vtk.dataset(x="x", y="y", z="z") + assert np.array_equal( + ds["RTData"].values.ravel(), truth.point_data["RTData"].ravel() + ) + assert np.may_share_memory( + ds["RTData"].values.ravel(), truth.point_data["RTData"].ravel() + ) + assert np.array_equal(mesh.x_coordinates, truth_r.x_coordinates) + assert np.array_equal(mesh.y_coordinates, truth_r.y_coordinates) + assert np.array_equal(mesh.z_coordinates, truth_r.z_coordinates) + compare_ds( + mesh, + truth_r, + "x_coordinates", + "y_coordinates", + "z_coordinates", + "RTData", + ) + + +def test_convert_vts(vts_path): + truth = vtk_read(vts_path) + ds = dataset_to_xarray(truth) + assert np.array_equal( + ds["Elevation"].values.ravel(), truth.point_data["Elevation"].ravel() + ) + assert np.may_share_memory( + ds["Elevation"].values.ravel(), truth.point_data["Elevation"].ravel() + ) + mesh = ds["Elevation"].vtk.dataset(x="x", y="y", z="z") + assert np.array_equal(mesh.x_coordinates, truth.x_coordinates) + assert np.array_equal(mesh.y_coordinates, truth.y_coordinates) + assert np.array_equal(mesh.z_coordinates, truth.z_coordinates) + compare_ds( + mesh, + truth, + "x_coordinates", + "y_coordinates", + "z_coordinates", + "Elevation", + ) From dfb767e018d8f8dc8dd852e065f2711b41fdf463 Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Tue, 29 Oct 2024 17:46:32 -0600 Subject: [PATCH 02/39] fix(xarray): add algo support --- examples/jupyter/test-xarray.ipynb | 216 ++++++++++++++++++++ pan3d/explorers/data_viewer.py | 189 ++++++++++++++++++ pan3d/xarray/algorithm.py | 310 +++++++++++++++++++++++++++++ pan3d/xarray/datasets.py | 2 +- 4 files changed, 716 insertions(+), 1 deletion(-) create mode 100644 examples/jupyter/test-xarray.ipynb create mode 100644 pan3d/explorers/data_viewer.py create mode 100644 pan3d/xarray/algorithm.py diff --git a/examples/jupyter/test-xarray.ipynb b/examples/jupyter/test-xarray.ipynb new file mode 100644 index 00000000..4e9f011c --- /dev/null +++ b/examples/jupyter/test-xarray.ipynb @@ -0,0 +1,216 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "88a3053b-a228-4099-8bd8-d92abaae317b", + "metadata": {}, + "outputs": [], + "source": [ + "from pan3d.explorers.data_viewer import XArrayViewer\n", + "import xarray as xr\n", + "from xarray.tutorial import open_dataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c66ae5de-ba4c-49f8-bcae-3572bd59cfa0", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = xr.open_dataset(\"../example_dataset.nc\", engine=\"netcdf4\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "41a4ebf1-8b90-4709-8d4c-06efb3afcc51", + "metadata": { + "collapsed": true, + "jupyter": { + "outputs_hidden": true + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/sebastien.jourdain/Documents/code/sbir/pan3d/.venv/lib/python3.10/site-packages/xarray/conventions.py:286: SerializationWarning: variable 'z' has non-conforming '_FillValue' np.float64(nan) defined, dropping '_FillValue' entirely.\n", + " var = coder.decode(var, name=name)\n", + "/Users/sebastien.jourdain/Documents/code/sbir/pan3d/.venv/lib/python3.10/site-packages/xarray/conventions.py:286: SerializationWarning: variable 'u' has non-conforming '_FillValue' np.float64(nan) defined, dropping '_FillValue' entirely.\n", + " var = coder.decode(var, name=name)\n", + "/Users/sebastien.jourdain/Documents/code/sbir/pan3d/.venv/lib/python3.10/site-packages/xarray/conventions.py:286: SerializationWarning: variable 'v' has non-conforming '_FillValue' np.float64(nan) defined, dropping '_FillValue' entirely.\n", + " var = coder.decode(var, name=name)\n" + ] + } + ], + "source": [ + "dataset = open_dataset(\"eraint_uvz\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "54c88fe2-176a-4468-89e3-3dbf2979776a", + "metadata": { + "collapsed": true, + "jupyter": { + "outputs_hidden": true + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "ERROR:root:Err: 0 Type: [Syntax Error] Msg: ERR201 - Undefined symbol: 'u'\tExpression: u*iHat + v*jHat\n", + "ERROR:root:Err: 0 Type: [Syntax Error] Msg: ERR201 - Undefined symbol: 'u'\tExpression: u*iHat + v*jHat\n", + "ERROR:root:Err: 0 Type: [Syntax Error] Msg: ERR201 - Undefined symbol: 'u'\tExpression: u*u + v*v\n", + "ERROR:root:Err: 0 Type: [Syntax Error] Msg: ERR201 - Undefined symbol: 'u'\tExpression: u*u + v*v\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "viewer = XArrayViewer()\n", + "await viewer.ui.ready" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "c78e6b6c-6ea0-4f46-ada1-8760ed86474f", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fbd9427e7e9e437fb5ac8e0de61dc9c3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HTML(value='