Skip to content

Commit

Permalink
ENH: Add dict_from_polyline, polyline_from_dict
Browse files Browse the repository at this point in the history
Support numpy-based and Python dictionary representation of
itk.PolyLineParametricPath.

Closes InsightSoftwareConsortium#3278
  • Loading branch information
thewtex committed May 2, 2024
1 parent 90a02a9 commit 3777b45
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 0 deletions.
44 changes: 44 additions & 0 deletions Wrapping/Generators/Python/PyBase/pyBase.i
Expand Up @@ -735,6 +735,50 @@ str = str
%enddef
%define DECL_PYTHON_POLYLINEPARAMETRICPATH_CLASS(swig_name)
%extend swig_name {
%pythoncode %{
def keys(self):
"""
Return keys related to the polyline's metadata.
These keys are used in the dictionary resulting from dict(polyline).
"""
result = ['name', 'vertexList']
return result
def __getitem__(self, key):
"""Access metadata keys, see help(pointset.keys), for string keys."""
import itk
if isinstance(key, str):
state = itk.dict_from_polyline(self)
return state[key]
def __setitem__(self, key, value):
if isinstance(key, str):
import numpy as np
if key == 'name':
self.SetObjectName(value)
elif key == 'vertexList':
self.GetVertexList().Initialize()
for vertex in value:
polyline.AddVertex(vertex)
def __getstate__(self):
"""Get object state, necessary for serialization with pickle."""
import itk
state = itk.dict_from_polyline(self)
return state
def __setstate__(self, state):
"""Set object state, necessary for serialization with pickle."""
import itk
deserialized = itk.polyline_from_dict(state)
self.__dict__['this'] = deserialized
%}
}
%enddef
%define DECL_PYTHON_MESH_CLASS(swig_name)
%extend swig_name {
%pythoncode %{
Expand Down
14 changes: 14 additions & 0 deletions Wrapping/Generators/Python/Tests/extras.py
Expand Up @@ -234,6 +234,20 @@ def custom_callback(name, progress):
pointset_dict = itk.dict_from_pointset(pointset)
pointset_back = itk.pointset_from_dict(pointset_dict)

polyline = itk.PolyLineParametricPath[dim].New()
polyline.AddVertex([0.0, 0.0])
polyline.AddVertex([1.0, 1.0])
polyline.AddVertex([4.0, 3.0])
polyline_dict = itk.dict_from_polyline(polyline)
polyline_back = itk.polyline_from_dict(polyline_dict)
original_vertices = itk.array_from_vector_container(polyline.GetVertexList())
back_vertices = itk.array_from_vector_container(polyline_back.GetVertexList())
assert np.allclose(original_vertices, back_vertices)

serialize_deserialize = pickle.loads(pickle.dumps(polyline))
back_vertices = itk.array_from_vector_container(serialize_deserialize.GetVertexList())
assert np.allclose(original_vertices, back_vertices)

# test search
res = itk.search("Index")
assert res[0] == "Index"
Expand Down
26 changes: 26 additions & 0 deletions Wrapping/Generators/Python/itk/support/extras.py
Expand Up @@ -103,6 +103,8 @@
"dict_from_mesh",
"pointset_from_dict",
"dict_from_pointset",
"polyline_from_dict",
"dict_from_polyline",
"transform_from_dict",
"dict_from_transform",
"transformwrite",
Expand Down Expand Up @@ -981,6 +983,30 @@ def dict_from_pointset(pointset: "itkt.PointSet") -> Dict:
)


def polyline_from_dict(polyline_dict: Dict) -> "itkt.PolylineParametricPath":
"""Deserialize an dictionary representing an itk.PolylineParametricPath object."""
import itk

vertex_list = polyline_dict["vertexList"]
dimension = vertex_list.shape[1]
polyline = itk.PolyLineParametricPath[dimension].New()
polyline.SetObjectName(polyline_dict["name"])
for vertex in vertex_list:
polyline.AddVertex(vertex)

return polyline

def dict_from_polyline(polyline: "itkt.PolylineParametricPath") -> Dict:
"""Serialize a Python itk.PolylineParametricPath object to a pickable Python dictionary."""
import itk

vertex_list = polyline.GetVertexList()
vertex_list_array = itk.array_from_vector_container(vertex_list)
return dict(
name=polyline.GetObjectName(),
vertexList=vertex_list_array,
)

def dict_from_transform(transform: "itkt.TransformBase") -> Dict:
import itk

Expand Down
4 changes: 4 additions & 0 deletions Wrapping/TypedefMacros.cmake
Expand Up @@ -639,6 +639,10 @@ macro(itk_wrap_simple_type wrap_class swig_name)
string(APPEND ITK_WRAP_PYTHON_SWIG_EXT "DECL_PYTHON_POINTSET_CLASS(${swig_name})\n\n")
endif()

if("${cpp_name}" STREQUAL "itk::PolyLineParametricPath")
string(APPEND ITK_WRAP_PYTHON_SWIG_EXT "DECL_PYTHON_POLYLINEPARAMETRICPATH_CLASS(${swig_name})\n\n")
endif()

if("${cpp_name}" STREQUAL "itk::Mesh")
string(APPEND ITK_WRAP_PYTHON_SWIG_EXT "DECL_PYTHON_MESH_CLASS(${swig_name})\n\n")
endif()
Expand Down

0 comments on commit 3777b45

Please sign in to comment.