In [12]:
import itk

from itkwidgets import view

In [13]:
PixelType = itk.F
Dimension = 3
    
# Read tre file
tubesReader = itk.SpatialObjectReader[Dimension].New()
tubesReader.SetFileName("data/Normal071-VascularNetwork.tre")
tubesReader.Update()
tubes = tubesReader.GetGroup()

# Read mra image
mraReader = itk.ImageFileReader[itk.Image[PixelType, Dimension]].New()
mraReader.SetFileName("data/Normal071-MRA.mha")
mraReader.Update()
mra = mraReader.GetOutput()

In [14]:
view(image=mra, point_sets=tubes)



In [15]:
print("Number of objects = ", tubes.GetNumberOfChildren())

sobj = tubes.GetChildren(0, "VesselTube")
baseSO = sobj[0]

print("Children are all maintained as base spatial object types - not as tubes, groups, landmarks, etc.")
print("  You can print info about the object:")
print(baseSO)
print("  But you cannot call member functions in derived classes (e.g., TubeSO member functions):")
print(baseSO.GetNumberOfPoints())   # This command fails - it should fail...and the next cell shows the fix...


Number of objects =  265
Children are all maintained as base spatial object types - not as tubes, groups, landmarks, etc.
  You can print info about the object:
TubeSpatialObject (0x7f7568024ca0)
  TubeSpatialObject(0x7f7568024ca0)
  End Type : 1
  Parent Point : -1
  Root : 1
  PointBasedSpatialObject(0x7f7568024ca0)
  Number of points: 4330
  RTTI typeinfo:   itk::TubeSpatialObject<3u, itk::TubeSpatialObjectPoint<3u> >
  Reference Count: 4
  Modified Time: 162989
  Debug: Off
  Object Name: 
  Observers: 
    none
  Source: (none)
  Source output name: (none)
  Release Data: Off
  Data Released: False
  Global Release Data: Off
  PipelineMTime: 0
  UpdateMTime: 0
  RealTimeStamp: 0 seconds 
  Id:0
  TypeName:VesselTubeSpatialObject
  ParentId:265
  Parent:0x4a87440
  LargestPossibleRegion:ImageRegion (0x7f7568024e18)
  Dimension: 3
  Index: [0, 0, 0]
  Size: [0, 0, 0]

  RequestedRegion:ImageRegion (0x7f7568024e50)
  Dimension: 3
  Index: [0, 0, 0]
  Size: [0, 0, 0]

  BufferedRegion:ImageRegion (0x7f7568024e88)
  Dimension: 3
  Index: [0, 0, 0]
  Size: [0, 0, 0]

  My Bounding Box In Object Space:
  BoundingBox (0x4664980)
  RTTI typeinfo:   itk::BoundingBox<unsigned long, 3u, double, itk::VectorContainer<unsigned long, itk::Point<double, 3u> > >
  Reference Count: 2
  Modified Time: 158538
  Debug: Off
  Object Name: 
  Observers: 
    none
  Bounding Box: ( 0,0 0,0 0,0  )

  My Bounding Box In World Space:
  BoundingBox (0x16af7670)
  RTTI typeinfo:   itk::BoundingBox<unsigned long, 3u, double, itk::VectorContainer<unsigned long, itk::Point<double, 3u> > >
  Reference Count: 2
  Modified Time: 158539
  Debug: Off
  Object Name: 
  Observers: 
    none
  Bounding Box: ( 0,0 0,0 0,0  )

  Family Bounding Box In Object Space:
  BoundingBox (0x16af7770)
  RTTI typeinfo:   itk::BoundingBox<unsigned long, 3u, double, itk::VectorContainer<unsigned long, itk::Point<double, 3u> > >
  Reference Count: 2
  Modified Time: 158540
  Debug: Off
  Object Name: 
  Observers: 
    none
  Bounding Box: ( 0,0 0,0 0,0  )

  Family Bounding Box In World Space:
  BoundingBox (0x26ed04c0)
  RTTI typeinfo:   itk::BoundingBox<unsigned long, 3u, double, itk::VectorContainer<unsigned long, itk::Point<double, 3u> > >
  Reference Count: 2
  Modified Time: 158541
  Debug: Off
  Object Name: 
  Observers: 
    none
  Bounding Box: ( 0,0 0,0 0,0  )

  Object to World Transform: AffineTransform (0x4a88c80)
  RTTI typeinfo:   itk::AffineTransform<double, 3u>
  Reference Count: 2
  Modified Time: 162987
  Debug: Off
  Object Name: 
  Observers: 
    none
  Matrix: 
    1 0 0 
    0 1 0 
    0 0 1 
  Offset: [0, 0, 0]
  Center: [0, 0, 0]
  Translation: [0, 0, 0]
  Inverse: 
    1 0 0 
    0 1 0 
    0 0 1 
  Singular: 0

  Object to World Transform Inverse: AffineTransform (0x26ed0650)
  RTTI typeinfo:   itk::AffineTransform<double, 3u>
  Reference Count: 2
  Modified Time: 162988
  Debug: Off
  Object Name: 
  Observers: 
    none
  Matrix: 
    1 0 0 
    0 1 0 
    0 0 1 
  Offset: [-0, -0, -0]
  Center: [0, 0, 0]
  Translation: [0, 0, 0]
  Inverse: 
    1 0 0 
    0 1 0 
    0 0 1 
  Singular: 0

  Object to Parent Transform: AffineTransform (0x18b49950)
  RTTI typeinfo:   itk::AffineTransform<double, 3u>
  Reference Count: 2
  Modified Time: 162981
  Debug: Off
  Object Name: 
  Observers: 
    none
  Matrix: 
    1 0 0 
    0 1 0 
    0 0 1 
  Offset: [0, 0, 0]
  Center: [0, 0, 0]
  Translation: [0, 0, 0]
  Inverse: 
    1 0 0 
    0 1 0 
    0 0 1 
  Singular: 0

  Object to Parent Transform Inverse: AffineTransform (0x4a889d0)
  RTTI typeinfo:   itk::AffineTransform<double, 3u>
  Reference Count: 2
  Modified Time: 162982
  Debug: Off
  Object Name: 
  Observers: 
    none
  Matrix: 
    1 0 0 
    0 1 0 
    0 0 1 
  Offset: [-0, -0, -0]
  Center: [0, 0, 0]
  Translation: [0, 0, 0]
  Inverse: 
    1 0 0 
    0 1 0 
    0 0 1 
  Singular: 0



  Object properties: 
  ChildrenList:0
  DefaultInsideValue:1
  DefaultOutsideValue:0

  But you cannot call member functions in derived classes (e.g., TubeSO member functions):
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-15-49cb51651c9d> in <module>()
      8 print(baseSO)
      9 print("  But you cannot call member functions in derived classes (e.g., TubeSO member functions):")
---> 10 print(baseSO.GetNumberOfPoints())   # This command fails - it should fail...and the next cell shows the fix...

AttributeError: 'itkSpatialObject3' object has no attribute 'GetNumberOfPoints'

In [16]:
print("One option is to downcast each object in the children list, as needed")

import itkExtras

baseSOTyped = itkExtras.down_cast(baseSO)

print("  Now we can call member functions of the derived class")
print(baseSOTyped.GetNumberOfPoints())   # This command succeeds on the down-casted variable


One option is to downcast each object in the children list, as needed
  Now we can call member functions of the derived class
4330

In [17]:
print("Another option is to use CastSpatialObject class to convert base spatial objects of a particular type...")
castSO = itk.CastSpatialObjectFilter[3].New()
castSO.SetInput(tubes)
tubesSO = castSO.GetTubes()


Another option is to use CastSpatialObject class to convert base spatial objects of a particular type...

In [18]:
print("Then you can access its member functions...")
tube = tubesSO[0]
tube.GetPoints()[1].GetPositionInObjectSpace()


Then you can access its member functions...
Out[18]:
itkPointD3 ([121.292, 94.4135, 0.313261])

In [19]:
p = list(map(lambda x: tube.GetPoint(x).GetPositionInObjectSpace(), range(tube.GetNumberOfPoints())))
i = list(map(lambda x: mra.TransformPhysicalPointToIndex( x ), p ))
for x in i:
    mra.SetPixel(x, 10000)
    
view(mra)