374 lines
8.2 KiB
Markdown
374 lines
8.2 KiB
Markdown
# Python API Usage
|
||
|
||
The `uLib` Python package is split into two sub-modules mirroring the C++ library:
|
||
|
||
| Sub-module | Contents |
|
||
|---|---|
|
||
| `uLib.Core` | Low-level utilities: `Object`, `Timer`, `Options`, `TypeRegister` |
|
||
| `uLib.Math` | Geometry, grids, voxel images, ray-tracing, image filters |
|
||
|
||
```python
|
||
import uLib
|
||
# Sub-modules are accessible as attributes
|
||
uLib.Core # core utilities
|
||
uLib.Math # mathematical structures
|
||
```
|
||
|
||
---
|
||
|
||
## uLib.Core
|
||
|
||
### Object
|
||
|
||
Base class for uLib objects; exposed to Python for type-hierarchy purposes.
|
||
|
||
```python
|
||
obj = uLib.Core.Object()
|
||
copy = obj.DeepCopy()
|
||
```
|
||
|
||
### Timer
|
||
|
||
Precision wall-clock timer.
|
||
|
||
```python
|
||
import time
|
||
timer = uLib.Core.Timer()
|
||
timer.Start()
|
||
time.sleep(0.5)
|
||
elapsed = timer.StopWatch() # returns elapsed seconds as float
|
||
print(f"Elapsed: {elapsed:.3f} s")
|
||
```
|
||
|
||
### Options
|
||
|
||
Wraps Boost.ProgramOptions for INI-style configuration files.
|
||
|
||
```python
|
||
opt = uLib.Core.Options("My Program")
|
||
opt.parse_config_file("config.ini") # load settings
|
||
n = opt.count("my_key") # check if key exists
|
||
opt.save_config_file("out.ini")
|
||
```
|
||
|
||
---
|
||
|
||
## uLib.Math – Linear Algebra
|
||
|
||
The math module exposes Eigen3 vectors and matrices as well-typed Python objects with NumPy interoperability.
|
||
|
||
### Fixed-size Vectors
|
||
|
||
```python
|
||
import numpy as np
|
||
import uLib
|
||
|
||
# Construct from list
|
||
v3 = uLib.Math.Vector3f([1.0, 2.0, 3.0])
|
||
print(v3[0], v3[1], v3[2]) # 1.0 2.0 3.0
|
||
|
||
# Construct from NumPy array
|
||
arr = np.array([4.0, 5.0, 6.0], dtype=np.float32)
|
||
v3b = uLib.Math.Vector3f(arr)
|
||
|
||
# Zero-initialise
|
||
v4d = uLib.Math.Vector4d() # all zeros
|
||
|
||
# Available types
|
||
# Vector1f / 2f / 3f / 4f (float32)
|
||
# Vector1d / 2d / 3d / 4d (float64)
|
||
# Vector1i / 2i / 3i / 4i (int32)
|
||
```
|
||
|
||
### Fixed-size Matrices
|
||
|
||
```python
|
||
# 2-by-2 float matrix
|
||
m2f = uLib.Math.Matrix2f()
|
||
m2f[0, 0] = 1; m2f[0, 1] = 2
|
||
m2f[1, 0] = 3; m2f[1, 1] = 4
|
||
|
||
# From list (row-major)
|
||
m4f = uLib.Math.Matrix4f([1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1])
|
||
|
||
# From NumPy (2-D array)
|
||
mat = np.eye(3, dtype=np.float32)
|
||
m3f = uLib.Math.Matrix3f(mat)
|
||
|
||
# Dynamic matrices
|
||
mXf = uLib.Math.MatrixXf(4, 4) # 4×4 float, zeros
|
||
```
|
||
|
||
### Homogeneous Types
|
||
|
||
```python
|
||
# HPoint3f – a 3-D point in homogeneous coordinates (w = 1)
|
||
p = uLib.Math.HPoint3f(1.0, 2.0, 3.0)
|
||
|
||
# HVector3f – a free vector (w = 0)
|
||
v = uLib.Math.HVector3f(0.0, 1.0, 0.0)
|
||
|
||
# HLine3f – a parametric ray
|
||
line = uLib.Math.HLine3f()
|
||
line.origin = uLib.Math.HPoint3f(0, 0, 0)
|
||
line.direction = uLib.Math.HVector3f(0, 0, 1)
|
||
```
|
||
|
||
---
|
||
|
||
## uLib.Math – Transforms and Geometry
|
||
|
||
### AffineTransform
|
||
|
||
A rigid-body / affine transform stored as a 4×4 matrix.
|
||
|
||
```python
|
||
tf = uLib.Math.AffineTransform()
|
||
|
||
tf.SetPosition([1.0, 0.0, 0.0]) # translate
|
||
tf.Translate([0.0, 1.0, 0.0]) # cumulative translate
|
||
tf.Scale([2.0, 2.0, 2.0]) # uniform scale
|
||
tf.Rotate(uLib.Math.Vector3f([0, 0, 3.14159])) # Euler angles (rad)
|
||
|
||
mat4 = tf.GetWorldMatrix() # 4×4 matrix
|
||
pos = tf.GetPosition() # Vector3f
|
||
```
|
||
|
||
### Geometry
|
||
|
||
Inherits `AffineTransform`; converts points between world and local frames.
|
||
|
||
```python
|
||
geo = uLib.Math.Geometry()
|
||
geo.SetPosition([1.0, 1.0, 1.0])
|
||
|
||
world_pt = uLib.Math.Vector4f([2.0, 3.0, 2.0, 1.0])
|
||
local_pt = geo.GetLocalPoint(world_pt)
|
||
back = geo.GetWorldPoint(local_pt)
|
||
# back ≈ [2, 3, 2, 1]
|
||
```
|
||
|
||
### ContainerBox
|
||
|
||
An axis-aligned bounding box with an associated transform.
|
||
|
||
```python
|
||
box = uLib.Math.ContainerBox()
|
||
box.SetOrigin([-1.0, -1.0, -1.0])
|
||
box.SetSize([2.0, 2.0, 2.0])
|
||
print(box.GetSize()) # [2, 2, 2]
|
||
```
|
||
|
||
---
|
||
|
||
## uLib.Math – Structured Grids
|
||
|
||
### StructuredGrid (3-D)
|
||
|
||
A 3-D voxel grid (origin, spacing, and integer dimensions).
|
||
|
||
```python
|
||
dims = uLib.Math.Vector3i([10, 10, 10])
|
||
grid = uLib.Math.StructuredGrid(dims)
|
||
grid.SetSpacing([1.0, 1.0, 1.0])
|
||
grid.SetOrigin([0.0, 0.0, 0.0])
|
||
|
||
print(grid.GetSpacing()) # [1, 1, 1]
|
||
print(grid.IsInsideBounds([5, 5, 5, 1])) # True
|
||
idx = grid.Find([2.5, 2.5, 2.5]) # returns grid cell index
|
||
```
|
||
|
||
### Structured2DGrid / Structured4DGrid
|
||
|
||
```python
|
||
grid2d = uLib.Math.Structured2DGrid()
|
||
grid2d.SetDims([100, 100])
|
||
grid2d.SetPhysicalSpace([0, 0], [1, 1])
|
||
print(grid2d.GetSpacing())
|
||
```
|
||
|
||
---
|
||
|
||
## uLib.Math – VoxImage
|
||
|
||
`VoxImage` is a 3-D voxel volume where each cell stores a `Voxel` ( `.Value` + `.Count`).
|
||
|
||
```python
|
||
dims = uLib.Math.Vector3i([20, 20, 20])
|
||
img = uLib.Math.VoxImage(dims)
|
||
img.SetSpacing([0.5, 0.5, 0.5])
|
||
|
||
# Access by linear index
|
||
img.SetValue(0, 42.0)
|
||
print(img.GetValue(0)) # 42.0
|
||
|
||
# Access by 3-D index
|
||
img.SetValue(uLib.Math.Vector3i([1, 1, 1]), 7.5)
|
||
print(img.GetValue(uLib.Math.Vector3i([1, 1, 1]))) # 7.5
|
||
|
||
# Clipping / masking helpers
|
||
cropped = img.clipImage(uLib.Math.Vector3i([2, 2, 2]),
|
||
uLib.Math.Vector3i([18, 18, 18]))
|
||
masked = img.maskImage(0.0, 100.0, 0.0) # mask outside [0, 100]
|
||
|
||
# I/O
|
||
img.ExportToVti("output.vti")
|
||
img.ImportFromVti("output.vti")
|
||
```
|
||
|
||
### Voxel (element type)
|
||
|
||
```python
|
||
vox = uLib.Math.Voxel()
|
||
vox.Value = 1.5
|
||
vox.Count = 3
|
||
|
||
data = img.Data() # returns the underlying Vector_Voxel
|
||
vox0 = data[0]
|
||
print(vox0.Value, vox0.Count)
|
||
```
|
||
|
||
---
|
||
|
||
## uLib.Math – VoxRaytracer
|
||
|
||
Performs ray-tracing through a `StructuredGrid` and returns per-voxel chord lengths.
|
||
|
||
```python
|
||
import numpy as np
|
||
import uLib
|
||
|
||
grid = uLib.Math.StructuredGrid([10, 10, 10])
|
||
grid.SetSpacing([1.0, 1.0, 1.0])
|
||
grid.SetOrigin([0.0, 0.0, 0.0])
|
||
|
||
rt = uLib.Math.VoxRaytracer(grid)
|
||
|
||
# Trace a ray between two homogeneous points (x, y, z, w=1)
|
||
p1 = np.array([0.5, 0.5, -1.0, 1.0], dtype=np.float32)
|
||
p2 = np.array([0.5, 0.5, 11.0, 1.0], dtype=np.float32)
|
||
result = rt.TraceBetweenPoints(p1, p2)
|
||
|
||
print("Voxels crossed:", result.Count())
|
||
print("Total length :", result.TotalLength())
|
||
|
||
elements = result.Data()
|
||
for i in range(result.Count()):
|
||
print(f" vox_id={elements[i].vox_id} L={elements[i].L:.4f}")
|
||
```
|
||
|
||
---
|
||
|
||
## uLib.Math – Image Filters
|
||
|
||
All filters share the same interface: construct with a kernel size, attach a `VoxImage`, optionally set parameters, then call `.Run()`.
|
||
|
||
```python
|
||
import uLib
|
||
|
||
dims = uLib.Math.Vector3i([10, 10, 10])
|
||
img = uLib.Math.VoxImage(dims)
|
||
for i in range(10**3):
|
||
img.SetValue(i, float(i))
|
||
|
||
kernel_dims = uLib.Math.Vector3i([3, 3, 3])
|
||
```
|
||
|
||
### Linear (Gaussian / Box) Filter
|
||
|
||
```python
|
||
filt = uLib.Math.VoxFilterAlgorithmLinear(kernel_dims)
|
||
filt.SetImage(img)
|
||
filt.SetKernelNumericXZY([1.0] * 27) # uniform box kernel, length = product of dims
|
||
filt.Run()
|
||
```
|
||
|
||
### ABTrim Filter
|
||
|
||
Applies alpha-beta trimming to remove outliers before averaging.
|
||
|
||
```python
|
||
filt = uLib.Math.VoxFilterAlgorithmAbtrim(kernel_dims)
|
||
filt.SetImage(img)
|
||
filt.SetKernelNumericXZY([1.0] * 27)
|
||
filt.SetABTrim(2, 2) # trim 2 low and 2 high values
|
||
filt.Run()
|
||
```
|
||
|
||
### Bilateral Filter
|
||
|
||
Edge-preserving smoothing controlled by a spatial sigma (from the kernel shape) and an intensity sigma.
|
||
|
||
```python
|
||
filt = uLib.Math.VoxFilterAlgorithmBilateral(kernel_dims)
|
||
filt.SetImage(img)
|
||
filt.SetKernelNumericXZY([1.0] * 27)
|
||
filt.SetIntensitySigma(0.3)
|
||
filt.Run()
|
||
```
|
||
|
||
### Threshold Filter
|
||
|
||
Zeros voxels below a threshold.
|
||
|
||
```python
|
||
filt = uLib.Math.VoxFilterAlgorithmThreshold(kernel_dims)
|
||
filt.SetImage(img)
|
||
filt.SetKernelNumericXZY([1.0] * 27)
|
||
filt.SetThreshold(0.5)
|
||
filt.Run()
|
||
```
|
||
|
||
### Median Filter
|
||
|
||
```python
|
||
filt = uLib.Math.VoxFilterAlgorithmMedian(kernel_dims)
|
||
filt.SetImage(img)
|
||
filt.SetKernelNumericXZY([1.0] * 27)
|
||
filt.Run()
|
||
```
|
||
|
||
---
|
||
|
||
## uLib.Math – Accumulators
|
||
|
||
Accumulators collect scalar samples and return a summary statistic.
|
||
|
||
```python
|
||
# Arithmetic mean
|
||
acc = uLib.Math.Accumulator_Mean_f()
|
||
acc(10.0)
|
||
acc(20.0)
|
||
mean = acc() # 15.0
|
||
|
||
# Alpha-beta trimmed mean
|
||
acc2 = uLib.Math.Accumulator_ABTrim_f()
|
||
acc2.SetABTrim(0.1, 0.1) # trim bottom 10 % and top 10 %
|
||
acc2 += 1.0
|
||
acc2 += 9999.0 # outlier
|
||
acc2 += 5.0
|
||
result = acc2() # trimmed mean ≈ 3.0
|
||
```
|
||
|
||
---
|
||
|
||
## Dynamic Vectors (`uLib.Math.Vector_*`)
|
||
|
||
Typed dynamic arrays backed by `uLib::Vector<T>` with optional CUDA memory management.
|
||
|
||
```python
|
||
# Integer vector
|
||
vi = uLib.Math.Vector_i()
|
||
vi.append(1); vi.append(2); vi.append(3)
|
||
print(len(vi), vi[0])
|
||
|
||
# Float vector with CUDA management
|
||
vf = uLib.Math.Vector_f()
|
||
vf.append(1.5)
|
||
vf.MoveToVRAM() # copy to GPU (no-op when CUDA is absent)
|
||
vf.MoveToRAM() # copy back to CPU
|
||
|
||
# Other types: Vector_ui, Vector_l, Vector_ul, Vector_d
|
||
# Compound element types: Vector_Vector3f, Vector_Vector4f, Vector_Voxel …
|
||
```
|