or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-structures.mdfiltering.mdfinite-difference.mdgpu-computing.mdimage-adaptors.mdimage-functions.mdindex.mdio.mdmesh.mdnumpy-integration.mdregistration.mdsegmentation.mdspatial-objects.mdtransforms.md

spatial-objects.mddocs/

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

```