Source code for cdiutils.io.vtk
import numpy as np
# handling vtk case
try:
import vtk
from vtk.util.numpy_support import numpy_to_vtk
IS_VTK_AVAILABLE = True
except ImportError:
IS_VTK_AVAILABLE = False
[docs]
class VtkImportError(ImportError):
"""Custom exception to handle Vtk import error."""
[docs]
def __init__(self, msg: str = None) -> None:
_msg = "vtk package is not installed."
if msg is not None:
_msg += "\n" + msg
super().__init__(_msg)
[docs]
def load_vtk(file_path: str):
"""
Load a vtk file.
Args:
file_path (_type_): the path to the file to open.
Raises:
VtkImportError: if vtk is not installed.
Returns:
the reader output
"""
if not IS_VTK_AVAILABLE:
raise VtkImportError
reader = vtk.vtkGenericDataObjectReader()
reader.SetFileName(file_path)
reader.ReadAllScalarsOn()
reader.ReadAllVectorsOn()
reader.ReadAllTensorsOn()
reader.Update()
return reader.GetOutput()
[docs]
def save_as_vti(
output_path: str,
voxel_size: tuple | list | np.ndarray,
cxi_convention: bool = False,
origin: tuple = (0, 0, 0),
**np_arrays: dict[np.ndarray],
) -> None:
"""Save numpy arrays to .vti file."""
if not IS_VTK_AVAILABLE:
raise VtkImportError
voxel_size = tuple(voxel_size)
nb_arrays = len(np_arrays)
if not nb_arrays:
raise ValueError(
"np_arrays is empty, please provide a dictionary of "
"(fieldnames: np.ndarray) you want to save."
)
is_init = False
for i, (key, array) in enumerate(np_arrays.items()):
if not is_init:
shape = array.shape
if cxi_convention:
# change order to match VTK (x, y, z) convention
voxel_size = (voxel_size[2], voxel_size[1], voxel_size[0])
shape = (shape[2], shape[1], shape[0])
image_data = vtk.vtkImageData()
image_data.SetOrigin(origin)
image_data.SetSpacing(voxel_size)
image_data.SetExtent(
0, shape[0] - 1, 0, shape[1] - 1, 0, shape[2] - 1
)
point_data = image_data.GetPointData()
is_init = True
if cxi_convention:
# natural ravelling row-major order is the one to use here,
# because, it will be x first, then y, then z.
vtk_array = numpy_to_vtk(array.ravel())
else: # convention XU (x, y z)
# here, row-major order does not match our needs, we need to
# transpose the array.
vtk_array = numpy_to_vtk(array.transpose(2, 1, 0).ravel())
point_data.AddArray(vtk_array)
point_data.GetArray(i).SetName(key)
point_data.Update()
writer = vtk.vtkXMLImageDataWriter()
writer.SetFileName(output_path)
writer.SetInputData(image_data)
writer.Write()