0
# Spatial Objects
1
2
Geometric object representations for modeling anatomical structures and regions of interest. ITK's spatial objects provide a hierarchical framework for representing geometric shapes, anatomical structures, and spatial relationships in medical imaging applications.
3
4
## Capabilities
5
6
### Base Spatial Object Classes
7
8
Foundation classes that define the spatial object hierarchy and common functionality.
9
10
```python { .api }
11
class SpatialObject[TDimension]:
12
"""
13
Base class for all spatial objects providing common spatial functionality.
14
15
Template Parameters:
16
- TDimension: Spatial dimensionality (typically 2 or 3)
17
"""
18
def New() -> SpatialObject[TDimension]: ...
19
def IsInside(self, point: Point[ScalarType, TDimension]) -> bool: ...
20
def IsInsideInObjectSpace(self, point: Point[ScalarType, TDimension]) -> bool: ...
21
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
22
def ComputeBoundingBox(self) -> BoundingBoxType: ...
23
def GetBoundingBox(self) -> BoundingBoxType: ...
24
def GetMyBoundingBoxInWorldSpace(self) -> BoundingBoxType: ...
25
def SetObjectToParentTransform(self, transform: TransformType) -> None: ...
26
def GetObjectToParentTransform(self) -> TransformType: ...
27
def SetObjectToWorldTransform(self, transform: TransformType) -> None: ...
28
def GetObjectToWorldTransform(self) -> TransformType: ...
29
def SetParent(self, parent: SpatialObject[TDimension]) -> None: ...
30
def GetParent(self) -> SpatialObject[TDimension]: ...
31
def AddChild(self, child: SpatialObject[TDimension]) -> None: ...
32
def RemoveChild(self, child: SpatialObject[TDimension]) -> None: ...
33
def GetChildren(self) -> list[SpatialObject[TDimension]]: ...
34
def GetNumberOfChildren(self) -> int: ...
35
def SetId(self, id: int) -> None: ...
36
def GetId(self) -> int: ...
37
def SetTypeName(self, name: str) -> None: ...
38
def GetTypeName(self) -> str: ...
39
def Update(self) -> None: ...
40
def GetMTime(self) -> ModifiedTimeType: ...
41
42
class GroupSpatialObject[TDimension]:
43
"""Container for multiple spatial objects."""
44
def New() -> GroupSpatialObject[TDimension]: ...
45
def AddChild(self, child: SpatialObject[TDimension]) -> None: ...
46
def RemoveChild(self, child: SpatialObject[TDimension]) -> None: ...
47
def GetChildren(self) -> list[SpatialObject[TDimension]]: ...
48
def GetNumberOfChildren(self) -> int: ...
49
def Clear(self) -> None: ...
50
51
class SceneSpatialObject[TDimension]:
52
"""Root spatial object containing a scene hierarchy."""
53
def New() -> SceneSpatialObject[TDimension]: ...
54
def AddSpatialObject(self, object: SpatialObject[TDimension]) -> None: ...
55
def RemoveSpatialObject(self, object: SpatialObject[TDimension]) -> None: ...
56
def GetObjects(self, depth: int = None, name: str = None) -> list[SpatialObject[TDimension]]: ...
57
def GetNumberOfObjects(self, depth: int = None, name: str = None) -> int: ...
58
def SetParentId(self, parent_id: int) -> None: ...
59
def GetParentId(self) -> int: ...
60
def FixHierarchy(self) -> None: ...
61
def CheckIdValidity(self) -> bool: ...
62
def FixIdValidity(self) -> bool: ...
63
def GetNextAvailableId(self) -> int: ...
64
```
65
66
### Geometric Primitive Objects
67
68
Basic geometric shapes and primitives.
69
70
```python { .api }
71
class EllipseSpatialObject[TDimension]:
72
"""Elliptical spatial object."""
73
def New() -> EllipseSpatialObject[TDimension]: ...
74
def SetRadiusInObjectSpace(self, radius: ArrayType) -> None: ...
75
def GetRadiusInObjectSpace(self) -> ArrayType: ...
76
def SetRadius(self, radius: ArrayType) -> None: ...
77
def GetRadius(self) -> ArrayType: ...
78
def SetCenterInObjectSpace(self, center: PointType) -> None: ...
79
def GetCenterInObjectSpace(self) -> PointType: ...
80
def IsInside(self, point: PointType) -> bool: ...
81
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
82
83
class BoxSpatialObject[TDimension]:
84
"""Box-shaped spatial object."""
85
def New() -> BoxSpatialObject[TDimension]: ...
86
def SetSizeInObjectSpace(self, size: SizeType) -> None: ...
87
def GetSizeInObjectSpace(self) -> SizeType: ...
88
def SetSize(self, size: SizeType) -> None: ...
89
def GetSize(self) -> SizeType: ...
90
def IsInside(self, point: PointType) -> bool: ...
91
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
92
93
class CylinderSpatialObject:
94
"""Cylindrical spatial object."""
95
def New() -> CylinderSpatialObject: ...
96
def SetRadius(self, radius: double) -> None: ...
97
def GetRadius(self) -> double: ...
98
def SetHeight(self, height: double) -> None: ...
99
def GetHeight(self) -> double: ...
100
def IsInside(self, point: PointType) -> bool: ...
101
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
102
103
class SphereSpatialObject[TDimension]:
104
"""Spherical spatial object."""
105
def New() -> SphereSpatialObject[TDimension]: ...
106
def SetRadiusInObjectSpace(self, radius: double) -> None: ...
107
def GetRadiusInObjectSpace(self) -> double: ...
108
def SetRadius(self, radius: double) -> None: ...
109
def GetRadius(self) -> double: ...
110
def IsInside(self, point: PointType) -> bool: ...
111
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
112
```
113
114
### Tubular Structure Objects
115
116
Objects for representing tubular and vessel-like structures.
117
118
```python { .api }
119
class TubeSpatialObject[TDimension, TTubePointType]:
120
"""
121
Spatial object representing tubular structures.
122
123
Template Parameters:
124
- TDimension: Spatial dimensionality
125
- TTubePointType: Type of points along the tube
126
"""
127
def New() -> TubeSpatialObject[TDimension, TTubePointType]: ...
128
def GetPoints(self) -> list[TTubePointType]: ...
129
def SetPoints(self, points: list[TTubePointType]) -> None: ...
130
def GetPoint(self, id: int) -> TTubePointType: ...
131
def SetPoint(self, id: int, point: TTubePointType) -> None: ...
132
def AddPoint(self, point: TTubePointType) -> None: ...
133
def RemovePoint(self, id: int) -> None: ...
134
def GetNumberOfPoints(self) -> int: ...
135
def Clear(self) -> None: ...
136
def IsInside(self, point: PointType) -> bool: ...
137
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
138
def ComputeTangentsAndNormals(self) -> None: ...
139
def RemoveDuplicatePointsInObjectSpace(self, min_spacing: double = 0) -> int: ...
140
141
class VesselTubeSpatialObject[TDimension]:
142
"""Specialized tube for blood vessel representation."""
143
def New() -> VesselTubeSpatialObject[TDimension]: ...
144
def GetPoints(self) -> list[VesselTubePointType]: ...
145
def SetPoints(self, points: list[VesselTubePointType]) -> None: ...
146
def ComputeTangentsAndNormals(self) -> None: ...
147
def SetRoot(self, root: bool) -> None: ...
148
def GetRoot(self) -> bool: ...
149
def SetParentPoint(self, point_id: int) -> None: ...
150
def GetParentPoint(self) -> int: ...
151
152
class DTITubeSpatialObject[TDimension]:
153
"""Tube spatial object for DTI fiber tracts."""
154
def New() -> DTITubeSpatialObject[TDimension]: ...
155
def GetPoints(self) -> list[DTITubePointType]: ...
156
def SetPoints(self, points: list[DTITubePointType]) -> None: ...
157
def ComputeTensorBasis(self) -> None: ...
158
```
159
160
### Point-Based Objects
161
162
Objects composed of collections of points with associated properties.
163
164
```python { .api }
165
class PointBasedSpatialObject[TDimension, TPointType]:
166
"""
167
Base class for spatial objects composed of points.
168
169
Template Parameters:
170
- TDimension: Spatial dimensionality
171
- TPointType: Type of spatial object points
172
"""
173
def GetPoints(self) -> list[TPointType]: ...
174
def SetPoints(self, points: list[TPointType]) -> None: ...
175
def GetPoint(self, id: int) -> TPointType: ...
176
def SetPoint(self, id: int, point: TPointType) -> None: ...
177
def AddPoint(self, point: TPointType) -> None: ...
178
def RemovePoint(self, id: int) -> None: ...
179
def GetNumberOfPoints(self) -> int: ...
180
def Clear(self) -> None: ...
181
def IsInside(self, point: PointType) -> bool: ...
182
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
183
184
class LineSpatialObject[TDimension]:
185
"""Line segment spatial object."""
186
def New() -> LineSpatialObject[TDimension]: ...
187
def GetPoints(self) -> list[LinePointType]: ...
188
def SetPoints(self, points: list[LinePointType]) -> None: ...
189
def GetNumberOfPoints(self) -> int: ...
190
def IsInside(self, point: PointType) -> bool: ...
191
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
192
193
class SurfaceSpatialObject[TDimension]:
194
"""Surface representation using points."""
195
def New() -> SurfaceSpatialObject[TDimension]: ...
196
def GetPoints(self) -> list[SurfacePointType]: ...
197
def SetPoints(self, points: list[SurfacePointType]) -> None: ...
198
def GetNumberOfPoints(self) -> int: ...
199
def IsInside(self, point: PointType) -> bool: ...
200
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
201
def ComputeNormals(self) -> None: ...
202
203
class LandmarkSpatialObject[TDimension]:
204
"""Collection of landmark points."""
205
def New() -> LandmarkSpatialObject[TDimension]: ...
206
def GetPoints(self) -> list[SpatialObjectPointType]: ...
207
def SetPoints(self, points: list[SpatialObjectPointType]) -> None: ...
208
def GetNumberOfPoints(self) -> int: ...
209
def IsInside(self, point: PointType) -> bool: ...
210
211
class ContourSpatialObject[TDimension]:
212
"""Contour curve representation."""
213
def New() -> ContourSpatialObject[TDimension]: ...
214
def GetPoints(self) -> list[ContourPointType]: ...
215
def SetPoints(self, points: list[ContourPointType]) -> None: ...
216
def GetNumberOfPoints(self) -> int: ...
217
def IsInside(self, point: PointType) -> bool: ...
218
def GetControlPoints(self) -> list[ContourPointType]: ...
219
def SetControlPoints(self, points: list[ContourPointType]) -> None: ...
220
def IsClosed(self) -> bool: ...
221
def SetClosed(self, closed: bool) -> None: ...
222
def ComputeLength(self) -> double: ...
223
```
224
225
### Image-Based Objects
226
227
Spatial objects that wrap or are derived from image data.
228
229
```python { .api }
230
class ImageSpatialObject[TDimension, TPixelType]:
231
"""
232
Spatial object that wraps an image.
233
234
Template Parameters:
235
- TDimension: Spatial dimensionality
236
- TPixelType: Image pixel type
237
"""
238
def New() -> ImageSpatialObject[TDimension, TPixelType]: ...
239
def SetImage(self, image: Image[TPixelType, TDimension]) -> None: ...
240
def GetImage(self) -> Image[TPixelType, TDimension]: ...
241
def IsInside(self, point: PointType) -> bool: ...
242
def IsInsideInObjectSpace(self, point: PointType) -> bool: ...
243
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
244
def SetSlicePosition(self, dimension: int, position: int) -> None: ...
245
def GetSlicePosition(self, dimension: int) -> int: ...
246
247
class ImageMaskSpatialObject[TDimension]:
248
"""Binary mask as spatial object."""
249
def New() -> ImageMaskSpatialObject[TDimension]: ...
250
def SetImage(self, image: Image[unsigned char, TDimension]) -> None: ...
251
def GetImage(self) -> Image[unsigned char, TDimension]: ...
252
def IsInside(self, point: PointType) -> bool: ...
253
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
254
def GetAxisAlignedBoundingBoxRegion(self) -> RegionType: ...
255
256
class BlobSpatialObject[TDimension]:
257
"""Blob representation for irregular regions."""
258
def New() -> BlobSpatialObject[TDimension]: ...
259
def GetPoints(self) -> list[BlobPointType]: ...
260
def SetPoints(self, points: list[BlobPointType]) -> None: ...
261
def GetNumberOfPoints(self) -> int: ...
262
def IsInside(self, point: PointType) -> bool: ...
263
def ComputeLocalBoundingBox(self) -> BoundingBoxType: ...
264
```
265
266
### Spatial Object Points
267
268
Point types used within spatial objects to store position and associated data.
269
270
```python { .api }
271
class SpatialObjectPoint[TPointDimension]:
272
"""Base class for spatial object points."""
273
def New() -> SpatialObjectPoint[TPointDimension]: ...
274
def SetPositionInObjectSpace(self, position: PointType) -> None: ...
275
def GetPositionInObjectSpace(self) -> PointType: ...
276
def SetPosition(self, position: PointType) -> None: ...
277
def GetPosition(self) -> PointType: ...
278
def SetColor(self, color: ColorType) -> None: ...
279
def GetColor(self) -> ColorType: ...
280
def SetRed(self, red: float) -> None: ...
281
def GetRed(self) -> float: ...
282
def SetGreen(self, green: float) -> None: ...
283
def GetGreen(self) -> float: ...
284
def SetBlue(self, blue: float) -> None: ...
285
def GetBlue(self) -> float: ...
286
def SetAlpha(self, alpha: float) -> None: ...
287
def GetAlpha(self) -> float: ...
288
def SetId(self, id: int) -> None: ...
289
def GetId(self) -> int: ...
290
291
class TubePoint[TPointDimension]:
292
"""Point along a tubular structure."""
293
def New() -> TubePoint[TPointDimension]: ...
294
def SetRadiusInObjectSpace(self, radius: float) -> None: ...
295
def GetRadiusInObjectSpace(self) -> float: ...
296
def SetRadius(self, radius: float) -> None: ...
297
def GetRadius(self) -> float: ...
298
def SetTangentInObjectSpace(self, tangent: VectorType) -> None: ...
299
def GetTangentInObjectSpace(self) -> VectorType: ...
300
def SetNormal1InObjectSpace(self, normal: VectorType) -> None: ...
301
def GetNormal1InObjectSpace(self) -> VectorType: ...
302
def SetNormal2InObjectSpace(self, normal: VectorType) -> None: ...
303
def GetNormal2InObjectSpace(self) -> VectorType: ...
304
305
class VesselTubePoint[TPointDimension]:
306
"""Vessel-specific tube point with additional properties."""
307
def New() -> VesselTubePoint[TPointDimension]: ...
308
def SetMedialness(self, medialness: float) -> None: ...
309
def GetMedialness(self) -> float: ...
310
def SetRidgeness(self, ridgeness: float) -> None: ...
311
def GetRidgeness(self) -> float: ...
312
def SetBranchness(self, branchness: float) -> None: ...
313
def GetBranchness(self) -> float: ...
314
def SetMark(self, mark: bool) -> None: ...
315
def GetMark(self) -> bool: ...
316
317
class DTITubePoint[TPointDimension]:
318
"""DTI tube point with tensor information."""
319
def New() -> DTITubePoint[TPointDimension]: ...
320
def SetTensorMatrix(self, tensor: MatrixType) -> None: ...
321
def GetTensorMatrix(self) -> MatrixType: ...
322
def AddField(self, name: str, value: float) -> None: ...
323
def GetField(self, name: str) -> float: ...
324
def SetFields(self, fields: FieldListType) -> None: ...
325
def GetFields(self) -> FieldListType: ...
326
327
class SurfacePoint[TPointDimension]:
328
"""Surface point with normal information."""
329
def New() -> SurfacePoint[TPointDimension]: ...
330
def SetNormalInObjectSpace(self, normal: VectorType) -> None: ...
331
def GetNormalInObjectSpace(self) -> VectorType: ...
332
def SetNormal(self, normal: VectorType) -> None: ...
333
def GetNormal(self) -> VectorType: ...
334
335
class ContourPoint[TPointDimension]:
336
"""Contour point with interpolation information."""
337
def New() -> ContourPoint[TPointDimension]: ...
338
def SetPickedPointInObjectSpace(self, point: PointType) -> None: ...
339
def GetPickedPointInObjectSpace(self) -> PointType: ...
340
def SetPickedPoint(self, point: PointType) -> None: ...
341
def GetPickedPoint(self) -> PointType: ...
342
343
class LinePoint[TPointDimension]:
344
"""Point along a line with direction information."""
345
def New() -> LinePoint[TPointDimension]: ...
346
def SetNormalInObjectSpace(self, normal: VectorType, index: int) -> None: ...
347
def GetNormalInObjectSpace(self, index: int) -> VectorType: ...
348
def SetNormal(self, normal: VectorType, index: int) -> None: ...
349
def GetNormal(self, index: int) -> VectorType: ...
350
```
351
352
## Usage Examples
353
354
### Creating Basic Geometric Objects
355
356
```python
357
import itk
358
import numpy as np
359
360
# Create a 3D scene
361
SceneType = itk.SceneSpatialObject[3]
362
scene = SceneType.New()
363
364
# Create an ellipse
365
EllipseType = itk.EllipseSpatialObject[3]
366
ellipse = EllipseType.New()
367
368
# Set ellipse properties
369
radius = itk.Vector[itk.D, 3]([10.0, 5.0, 3.0]) # Semi-axes lengths
370
ellipse.SetRadius(radius)
371
372
center = itk.Point[itk.D, 3]([0.0, 0.0, 0.0])
373
ellipse.SetCenterInObjectSpace(center)
374
375
# Create a transform to position the ellipse
376
TransformType = itk.AffineTransform[itk.D, 3]
377
transform = TransformType.New()
378
transform.SetIdentity()
379
380
# Translate ellipse
381
translation = itk.Vector[itk.D, 3]([20.0, 30.0, 40.0])
382
transform.SetTranslation(translation)
383
ellipse.SetObjectToParentTransform(transform)
384
385
# Add to scene
386
ellipse.SetId(1)
387
scene.AddSpatialObject(ellipse)
388
389
# Create a box
390
BoxType = itk.BoxSpatialObject[3]
391
box = BoxType.New()
392
393
box_size = itk.Vector[itk.D, 3]([15.0, 10.0, 8.0])
394
box.SetSize(box_size)
395
396
# Position the box
397
box_transform = TransformType.New()
398
box_transform.SetIdentity()
399
box_translation = itk.Vector[itk.D, 3]([-25.0, -15.0, 10.0])
400
box_transform.SetTranslation(box_translation)
401
box.SetObjectToParentTransform(box_transform)
402
403
box.SetId(2)
404
scene.AddSpatialObject(box)
405
406
# Create a sphere
407
SphereType = itk.SphereSpatialObject[3]
408
sphere = SphereType.New()
409
sphere.SetRadius(7.0)
410
411
sphere_transform = TransformType.New()
412
sphere_transform.SetIdentity()
413
sphere_translation = itk.Vector[itk.D, 3]([0.0, -30.0, -20.0])
414
sphere_transform.SetTranslation(sphere_translation)
415
sphere.SetObjectToParentTransform(sphere_transform)
416
417
sphere.SetId(3)
418
scene.AddSpatialObject(sphere)
419
420
print(f"Scene contains {scene.GetNumberOfObjects()} objects")
421
422
# Test point inclusion
423
test_points = [
424
itk.Point[itk.D, 3]([20.0, 30.0, 40.0]), # Center of ellipse
425
itk.Point[itk.D, 3]([-25.0, -15.0, 10.0]), # Center of box
426
itk.Point[itk.D, 3]([0.0, -30.0, -20.0]), # Center of sphere
427
itk.Point[itk.D, 3]([100.0, 100.0, 100.0]) # Outside all objects
428
]
429
430
objects = [ellipse, box, sphere]
431
object_names = ["Ellipse", "Box", "Sphere"]
432
433
for point in test_points:
434
print(f"\nTesting point {point}:")
435
for obj, name in zip(objects, object_names):
436
inside = obj.IsInside(point)
437
print(f" {name}: {'Inside' if inside else 'Outside'}")
438
```
439
440
### Working with Tubular Structures
441
442
```python
443
import itk
444
import numpy as np
445
446
# Create a vessel tube
447
VesselTubeType = itk.VesselTubeSpatialObject[3]
448
vessel = VesselTubeType.New()
449
450
# Create points along the vessel
451
VesselPointType = itk.VesselTubePoint[3]
452
points = []
453
454
# Create a curved vessel path
455
num_points = 20
456
for i in range(num_points):
457
point = VesselPointType.New()
458
459
# Position along a curved path
460
t = float(i) / (num_points - 1)
461
x = t * 50.0
462
y = 10.0 * np.sin(t * 2 * np.pi)
463
z = 5.0 * np.cos(t * 2 * np.pi)
464
465
position = itk.Point[itk.D, 3]([x, y, z])
466
point.SetPosition(position)
467
468
# Set radius that varies along the vessel
469
radius = 2.0 + 1.0 * np.sin(t * np.pi)
470
point.SetRadius(radius)
471
472
# Set vessel-specific properties
473
point.SetMedialness(0.8 + 0.2 * np.random.random())
474
point.SetRidgeness(0.7 + 0.3 * np.random.random())
475
point.SetBranchness(0.1 if i < num_points - 5 else 0.9) # Branch at end
476
477
# Set color
478
red = 0.8 + 0.2 * t
479
green = 0.2
480
blue = 0.2
481
point.SetRed(red)
482
point.SetGreen(green)
483
point.SetBlue(blue)
484
485
point.SetId(i)
486
points.append(point)
487
488
# Set points to vessel
489
vessel.SetPoints(points)
490
491
# Compute tangents and normals
492
vessel.ComputeTangentsAndNormals()
493
494
print(f"Vessel has {vessel.GetNumberOfPoints()} points")
495
496
# Access vessel properties
497
for i in range(0, num_points, 5): # Sample every 5th point
498
point = vessel.GetPoint(i)
499
pos = point.GetPosition()
500
radius = point.GetRadius()
501
medialness = point.GetMedialness()
502
503
print(f"Point {i}: Position=({pos[0]:.1f}, {pos[1]:.1f}, {pos[2]:.1f}), "
504
f"Radius={radius:.2f}, Medialness={medialness:.3f}")
505
506
# Test if points are inside the vessel
507
test_points = [
508
itk.Point[itk.D, 3]([10.0, 2.0, 1.0]), # Should be inside
509
itk.Point[itk.D, 3]([25.0, 10.0, 0.0]), # Near vessel path
510
itk.Point[itk.D, 3]([0.0, 20.0, 20.0]) # Far from vessel
511
]
512
513
for test_point in test_points:
514
inside = vessel.IsInside(test_point)
515
print(f"Point {test_point} is {'inside' if inside else 'outside'} vessel")
516
517
# Get bounding box
518
bbox = vessel.ComputeLocalBoundingBox()
519
bounds = bbox.GetBounds()
520
print(f"Vessel bounding box: X=[{bounds[0]:.1f}, {bounds[1]:.1f}], "
521
f"Y=[{bounds[2]:.1f}, {bounds[3]:.1f}], Z=[{bounds[4]:.1f}, {bounds[5]:.1f}]")
522
```
523
524
### Creating DTI Fiber Tracts
525
526
```python
527
import itk
528
import numpy as np
529
530
# Create DTI tube for fiber tract
531
DTITubeType = itk.DTITubeSpatialObject[3]
532
fiber_tract = DTITubeType.New()
533
534
# Create DTI points with tensor information
535
DTIPointType = itk.DTITubePoint[3]
536
dti_points = []
537
538
num_points = 15
539
for i in range(num_points):
540
point = DTIPointType.New()
541
542
# Position along fiber path
543
t = float(i) / (num_points - 1)
544
x = t * 30.0
545
y = 5.0 * np.sin(t * np.pi)
546
z = 2.0 * np.cos(t * 2 * np.pi)
547
548
position = itk.Point[itk.D, 3]([x, y, z])
549
point.SetPosition(position)
550
551
# Set basic tube properties
552
radius = 0.5 + 0.2 * np.random.random()
553
point.SetRadius(radius)
554
555
# Create tensor matrix (3x3 symmetric)
556
tensor = itk.Matrix[itk.D, 3, 3]()
557
558
# Principal direction along fiber
559
major_eigenvalue = 1.5e-3
560
minor_eigenvalue = 0.3e-3
561
562
# Create a simple tensor aligned with fiber direction
563
tensor.SetIdentity()
564
tensor.SetElement(0, 0, major_eigenvalue) # Along X (fiber direction)
565
tensor.SetElement(1, 1, minor_eigenvalue) # Perpendicular
566
tensor.SetElement(2, 2, minor_eigenvalue) # Perpendicular
567
568
point.SetTensorMatrix(tensor)
569
570
# Add custom fields (e.g., FA, MD)
571
fa = major_eigenvalue / (major_eigenvalue + 2 * minor_eigenvalue)
572
md = (major_eigenvalue + 2 * minor_eigenvalue) / 3.0
573
574
point.AddField("FA", fa)
575
point.AddField("MD", md)
576
point.AddField("Temperature", 37.0 + np.random.normal(0, 0.5))
577
578
point.SetId(i)
579
dti_points.append(point)
580
581
# Set points to DTI tube
582
fiber_tract.SetPoints(dti_points)
583
584
# Compute tensor basis
585
fiber_tract.ComputeTensorBasis()
586
587
print(f"DTI fiber tract has {fiber_tract.GetNumberOfPoints()} points")
588
589
# Access DTI properties
590
for i in range(0, num_points, 3): # Sample every 3rd point
591
point = fiber_tract.GetPoint(i)
592
pos = point.GetPosition()
593
tensor = point.GetTensorMatrix()
594
fa = point.GetField("FA")
595
md = point.GetField("MD")
596
597
print(f"Point {i}: Position=({pos[0]:.1f}, {pos[1]:.1f}, {pos[2]:.1f})")
598
print(f" FA={fa:.3f}, MD={md:.6f}")
599
print(f" Tensor diagonal: [{tensor.GetElement(0,0):.6f}, "
600
f"{tensor.GetElement(1,1):.6f}, {tensor.GetElement(2,2):.6f}]")
601
602
# Test point membership
603
test_point = itk.Point[itk.D, 3]([15.0, 2.5, 0.0]) # Midpoint of tract
604
inside = fiber_tract.IsInside(test_point)
605
print(f"Test point is {'inside' if inside else 'outside'} fiber tract")
606
```
607
608
### Working with Image-Based Spatial Objects
609
610
```python
611
import itk
612
import numpy as np
613
614
# Create a binary mask image
615
ImageType = itk.Image[itk.UC, 3]
616
mask_image = ImageType.New()
617
618
size = itk.Size[3]([50, 50, 20])
619
region = itk.ImageRegion[3]()
620
region.SetSize(size)
621
mask_image.SetRegions(region)
622
mask_image.SetSpacing([1.0, 1.0, 2.0])
623
mask_image.SetOrigin([0.0, 0.0, 0.0])
624
mask_image.Allocate()
625
626
# Create a spherical mask
627
center_x, center_y, center_z = 25, 25, 10
628
radius = 15
629
630
for x in range(50):
631
for y in range(50):
632
for z in range(20):
633
idx = itk.Index[3]([x, y, z])
634
# Account for spacing
635
world_x = x * 1.0
636
world_y = y * 1.0
637
world_z = z * 2.0
638
639
dist = np.sqrt((world_x - center_x)**2 +
640
(world_y - center_y)**2 +
641
(world_z - center_z)**2)
642
643
if dist <= radius:
644
mask_image.SetPixel(idx, 255)
645
else:
646
mask_image.SetPixel(idx, 0)
647
648
# Create image mask spatial object
649
ImageMaskType = itk.ImageMaskSpatialObject[3]
650
mask_object = ImageMaskType.New()
651
mask_object.SetImage(mask_image)
652
653
print("Created image mask spatial object")
654
655
# Test spatial queries
656
test_points = [
657
itk.Point[itk.D, 3]([25.0, 25.0, 10.0]), # Center (should be inside)
658
itk.Point[itk.D, 3]([35.0, 25.0, 10.0]), # Near edge
659
itk.Point[itk.D, 3]([45.0, 45.0, 30.0]) # Outside
660
]
661
662
for point in test_points:
663
inside = mask_object.IsInside(point)
664
print(f"Point {point} is {'inside' if inside else 'outside'} mask")
665
666
# Get bounding box
667
bbox = mask_object.ComputeLocalBoundingBox()
668
bounds = bbox.GetBounds()
669
print(f"Mask bounding box:")
670
print(f" X: [{bounds[0]:.1f}, {bounds[1]:.1f}]")
671
print(f" Y: [{bounds[2]:.1f}, {bounds[3]:.1f}]")
672
print(f" Z: [{bounds[4]:.1f}, {bounds[5]:.1f}]")
673
674
# Get axis-aligned bounding box region in image coordinates
675
bbox_region = mask_object.GetAxisAlignedBoundingBoxRegion()
676
bbox_size = bbox_region.GetSize()
677
bbox_index = bbox_region.GetIndex()
678
679
print(f"Bounding box region:")
680
print(f" Index: [{bbox_index[0]}, {bbox_index[1]}, {bbox_index[2]}]")
681
print(f" Size: [{bbox_size[0]}, {bbox_size[1]}, {bbox_size[2]}]")
682
683
# Create regular image spatial object
684
ImageSpatialObjectType = itk.ImageSpatialObject[3, itk.F]
685
image_object = ImageSpatialObjectType.New()
686
687
# Create a gradient image
688
FloatImageType = itk.Image[itk.F, 3]
689
gradient_image = FloatImageType.New()
690
gradient_image.SetRegions(region)
691
gradient_image.SetSpacing([1.0, 1.0, 2.0])
692
gradient_image.Allocate()
693
694
for x in range(50):
695
for y in range(50):
696
for z in range(20):
697
idx = itk.Index[3]([x, y, z])
698
value = float(x + y + z) / 3.0
699
gradient_image.SetPixel(idx, value)
700
701
image_object.SetImage(gradient_image)
702
703
# Test image-based spatial object
704
test_point = itk.Point[itk.D, 3]([25.0, 25.0, 20.0])
705
inside_image = image_object.IsInside(test_point)
706
print(f"Point {test_point} is {'inside' if inside_image else 'outside'} image object")
707
```
708
709
### Hierarchical Spatial Object Organization
710
711
```python
712
import itk
713
714
# Create a scene to organize spatial objects
715
SceneType = itk.SceneSpatialObject[3]
716
scene = SceneType.New()
717
718
# Create a group for anatomical structures
719
GroupType = itk.GroupSpatialObject[3]
720
anatomy_group = GroupType.New()
721
anatomy_group.SetId(100)
722
anatomy_group.SetTypeName("AnatomicalStructures")
723
724
# Create individual organs as children
725
# Heart (ellipsoid)
726
EllipseType = itk.EllipseSpatialObject[3]
727
heart = EllipseType.New()
728
heart.SetRadius(itk.Vector[itk.D, 3]([6.0, 4.0, 8.0]))
729
730
heart_transform = itk.AffineTransform[itk.D, 3].New()
731
heart_transform.SetIdentity()
732
heart_transform.SetTranslation(itk.Vector[itk.D, 3]([-2.0, 0.0, 5.0]))
733
heart.SetObjectToParentTransform(heart_transform)
734
heart.SetId(101)
735
heart.SetTypeName("Heart")
736
737
# Liver (box approximation)
738
BoxType = itk.BoxSpatialObject[3]
739
liver = BoxType.New()
740
liver.SetSize(itk.Vector[itk.D, 3]([12.0, 8.0, 6.0]))
741
742
liver_transform = itk.AffineTransform[itk.D, 3].New()
743
liver_transform.SetIdentity()
744
liver_transform.SetTranslation(itk.Vector[itk.D, 3]([8.0, -3.0, 2.0]))
745
liver.SetObjectToParentTransform(liver_transform)
746
liver.SetId(102)
747
liver.SetTypeName("Liver")
748
749
# Add organs to anatomy group
750
anatomy_group.AddChild(heart)
751
anatomy_group.AddChild(liver)
752
753
# Create a group for vascular structures
754
vascular_group = GroupType.New()
755
vascular_group.SetId(200)
756
vascular_group.SetTypeName("VascularStructures")
757
758
# Create blood vessels
759
VesselTubeType = itk.VesselTubeSpatialObject[3]
760
VesselPointType = itk.VesselTubePoint[3]
761
762
# Main vessel
763
main_vessel = VesselTubeType.New()
764
main_points = []
765
766
for i in range(10):
767
point = VesselPointType.New()
768
t = float(i) / 9.0
769
position = itk.Point[itk.D, 3]([t * 20.0 - 10.0, 0.0, 10.0])
770
point.SetPosition(position)
771
point.SetRadius(2.0 - t * 0.5) # Tapering vessel
772
point.SetId(i)
773
main_points.append(point)
774
775
main_vessel.SetPoints(main_points)
776
main_vessel.SetId(201)
777
main_vessel.SetTypeName("MainVessel")
778
main_vessel.SetRoot(True)
779
780
# Branch vessel
781
branch_vessel = VesselTubeType.New()
782
branch_points = []
783
784
for i in range(6):
785
point = VesselPointType.New()
786
t = float(i) / 5.0
787
position = itk.Point[itk.D, 3]([0.0, t * 8.0, 10.0])
788
point.SetPosition(position)
789
point.SetRadius(1.0 - t * 0.3)
790
point.SetId(i)
791
branch_points.append(point)
792
793
branch_vessel.SetPoints(branch_points)
794
branch_vessel.SetId(202)
795
branch_vessel.SetTypeName("BranchVessel")
796
branch_vessel.SetParentPoint(5) # Connected to point 5 of main vessel
797
798
# Add vessels to vascular group
799
vascular_group.AddChild(main_vessel)
800
vascular_group.AddChild(branch_vessel)
801
802
# Add groups to scene
803
scene.AddSpatialObject(anatomy_group)
804
scene.AddSpatialObject(vascular_group)
805
806
# Query the scene hierarchy
807
print(f"Scene contains {scene.GetNumberOfObjects()} top-level objects")
808
print(f"Total objects (all levels): {scene.GetNumberOfObjects(depth=None)}")
809
810
# Get objects by type
811
hearts = scene.GetObjects(depth=None, name="Heart")
812
vessels = scene.GetObjects(depth=None, name="*Vessel*") # Wildcard match
813
814
print(f"Found {len(hearts)} heart objects")
815
print(f"Found {len(vessels)} vessel objects")
816
817
# Test hierarchical point queries
818
test_point = itk.Point[itk.D, 3]([0.0, 0.0, 5.0])
819
820
print(f"\nTesting point {test_point}:")
821
print(f"Inside heart: {heart.IsInside(test_point)}")
822
print(f"Inside liver: {liver.IsInside(test_point)}")
823
print(f"Inside main vessel: {main_vessel.IsInside(test_point)}")
824
print(f"Inside anatomy group: {anatomy_group.IsInside(test_point)}")
825
826
# Navigate hierarchy
827
print("\nHierarchy structure:")
828
for top_obj in scene.GetChildren():
829
print(f"Top level: {top_obj.GetTypeName()} (ID: {top_obj.GetId()})")
830
for child in top_obj.GetChildren():
831
print(f" Child: {child.GetTypeName()} (ID: {child.GetId()})")
832
if hasattr(child, 'GetNumberOfPoints') and child.GetNumberOfPoints() > 0:
833
print(f" Points: {child.GetNumberOfPoints()}")
834
```