Files
geMoldInsight/venv/lib/python3.11/site-packages/vtkmodules/web/utils.py
T
2026-02-12 23:27:48 +08:00

212 lines
6.0 KiB
Python

try:
import numpy as np
except ImportError:
raise ImportError(
"This module depends on the numpy module. Please make\
sure that it is installed properly."
)
import base64
from vtkmodules.util.numpy_support import vtk_to_numpy
from vtkmodules.vtkFiltersGeometry import vtkDataSetSurfaceFilter
# Numpy to JS TypedArray
to_js_type = {
"int8": "Int8Array",
"uint8": "Uint8Array",
"int16": "Int16Array",
"uint16": "Uint16Array",
"int32": "Int32Array",
"uint32": "Uint32Array",
"int64": "Int32Array",
"uint64": "Uint32Array",
"float32": "Float32Array",
"float64": "Float64Array",
}
def b64_encode_numpy(obj):
# Convert 1D numpy arrays with numeric types to memoryviews with
# datatype and shape metadata.
if len(obj) == 0:
return obj.tolist()
dtype = obj.dtype
if dtype.kind == "f":
return np_encode(obj)
elif dtype.kind == "b":
return np_encode(obj, np.uint8)
elif dtype.kind in ["u", "i"]:
# Try to see if we can downsize the array
max_value = np.amax(obj)
min_value = np.amin(obj)
signed = min_value < 0
test_value = max(max_value, -min_value)
if signed:
if test_value < np.iinfo(np.int8):
return np_encode(obj, np.int8)
if test_value < np.iinfo(np.int16).max:
return np_encode(obj, np.int16)
if test_value < np.iinfo(np.int32).max:
return np_encode(obj, np.int32)
else:
if test_value < np.iinfo(np.uint8).max:
return np_encode(obj, np.uint8)
if test_value < np.iinfo(np.uint16).max:
return np_encode(obj, np.uint16)
if test_value < np.iinfo(np.uint32).max:
return np_encode(obj, np.uint32)
# Convert all other numpy arrays to lists
return obj.tolist()
def np_encode(array, np_type=None):
if np_type:
n_array = array.astype(np_type).ravel(order="C")
return {
"bvals": base64.b64encode(memoryview(n_array)).decode("utf-8"),
"dtype": str(n_array.dtype),
"shape": list(array.shape),
}
return {
"bvals": base64.b64encode(memoryview(array.ravel(order="C"))).decode("utf-8"),
"dtype": str(array.dtype),
"shape": list(array.shape),
}
def mesh_array(array):
if array:
return b64_encode_numpy(vtk_to_numpy(array.GetData()))
def data_array(data_array, location="PointData", name=None):
if data_array:
dataRange = data_array.GetRange(-1)
nb_comp = data_array.GetNumberOfComponents()
values = vtk_to_numpy(data_array)
js_types = to_js_type[str(values.dtype)]
return {
"name": name if name else data_array.GetName(),
"values": b64_encode_numpy(values),
"numberOfComponents": nb_comp,
"type": js_types,
"location": location,
"dataRange": dataRange,
}
def field_data(field_data, names, location="PointData"):
fields = []
for name in names:
array = field_data.GetArray(name)
js_array = data_array(array, location, name)
if js_array:
fields.append(js_array)
return fields
def mesh(dataset, field_to_keep=None, point_arrays=None, cell_arrays=None):
"""Expect any dataset and extract its surface into a dash_vtk.Mesh state property"""
if dataset is None:
return None
# Make sure we have a polydata to export
polydata = None
if dataset.IsA("vtkPolyData"):
polydata = dataset
else:
extractSkinFilter = vtkDataSetSurfaceFilter()
extractSkinFilter.SetInputData(dataset)
extractSkinFilter.Update()
polydata = extractSkinFilter.GetOutput()
if polydata.GetPoints() is None:
return None
# Extract mesh
state = {"mesh": {}}
points = mesh_array(polydata.GetPoints())
if points:
state["mesh"]["points"] = points
verts = mesh_array(polydata.GetVerts())
if verts:
state["mesh"]["verts"] = verts
lines = mesh_array(polydata.GetLines())
if lines:
state["mesh"]["lines"] = lines
polys = mesh_array(polydata.GetPolys())
if polys:
state["mesh"]["polys"] = polys
strips = mesh_array(polydata.GetStrips())
if strips:
state["mesh"]["strips"] = strips
# Scalars
if field_to_keep is not None:
field = None
p_array = polydata.GetPointData().GetArray(field_to_keep)
c_array = polydata.GetCellData().GetArray(field_to_keep)
if c_array:
field = data_array(c_array, location="CellData", name=field_to_keep)
if p_array:
field = data_array(p_array, location="PointData", name=field_to_keep)
if field:
state.update({"field": field})
# PointData Fields
if point_arrays:
point_data = field_data(polydata.GetPointData(), point_arrays, "PointData")
if len(point_data):
state.update({"pointArrays": point_data})
# CellData Fields
if cell_arrays:
cell_data = field_data(polydata.GetCellData(), cell_arrays, "CellData")
if len(cell_data):
state.update({"cellArrays": cell_data})
return state
def volume(dataset):
"""Expect a vtkImageData and extract its setting for the dash_vtk.Volume state"""
if dataset is None or not dataset.IsA("vtkImageData"):
return None
state = {
"image": {
"dimensions": dataset.GetDimensions(),
"spacing": dataset.GetSpacing(),
"origin": dataset.GetOrigin(),
},
}
# Capture image orientation if any
if hasattr(dataset, "GetDirectionMatrix"):
matrix = dataset.GetDirectionMatrix()
js_mat = []
for j in range(3):
for i in range(3):
js_mat.append(matrix.GetElement(i, j))
state["image"]["direction"] = js_mat
scalars = dataset.GetPointData().GetScalars()
field = data_array(scalars, location="PointData")
if field:
state["field"] = field
return state