High-performance N-dimensional unit field transformations with interpolation
Project description
UnitField
UnitField is a high-performance Python library for N-dimensional unit field transformations with interpolation. It provides efficient tools for mapping unit-space coordinates (values in [0, 1]) to transformed coordinates, with support for various interpolation methods and optimized backends.
Features
- N-dimensional unit field transformations with flexible interpolation
- Multiple interpolation methods: Nearest neighbor (Manhattan/Euclidean), Linear, Cubic, Lanczos4
- Dual backends: NumPy for N-dimensional fields, OpenCV for optimized 2D operations
- 2D image remapping with endomorphism composition
- Type-safe with comprehensive type hints
- Well-tested with extensive test coverage
- Performance optimized with LRU caching and vectorized operations
Installation
From Source
git clone https://github.com/Grayjou/UnitField.git
cd UnitField
pip install -e .
Requirements
- Python >= 3.8
- NumPy >= 1.20.0
- OpenCV (cv2) >= 4.5.0
- boundednumbers >= 0.1.0
- typing-extensions >= 4.0.0
Quick Start
Basic Unit Field Usage
import numpy as np
from unitfield.core.unitfield import MappedUnitField
from unitfield.core.enums import InterpMethod
# Create a 2D unit field (5x5 grid mapping to 2D vectors)
x, y = np.meshgrid(np.linspace(0, 1, 5), np.linspace(0, 1, 5))
data = np.stack([x, y], axis=-1)
# Create the field with linear interpolation
field = MappedUnitField(data=data, interp_method=InterpMethod.LINEAR)
# Query single coordinate
result = field.get_value((0.5, 0.5))
print(f"Value at (0.5, 0.5): {result}")
# Query multiple coordinates
coords = np.array([[0.0, 0.0], [0.5, 0.5], [1.0, 1.0]])
results = field.get_values(coords)
print(f"Batch results shape: {results.shape}")
2D Image Remapping with Endomorphisms
import numpy as np
import cv2
from unitfield.core.unitfield import Unit2DMappedEndomorphism
from unitfield.core.enums import InterpMethod
# Create an identity endomorphism
height, width = 100, 100
xs, ys = np.meshgrid(
np.linspace(0, 1, width),
np.linspace(0, 1, height),
indexing='xy'
)
identity_data = np.stack([xs, ys], axis=-1)
# Create endomorphism with cubic interpolation
endo = Unit2DMappedEndomorphism(
data=identity_data,
interp_method=InterpMethod.CUBIC
)
# Remap an image
image = cv2.imread('input.jpg')
remapped = endo.remap(image, interpolation=cv2.INTER_LINEAR)
# Compose two endomorphisms
endo2 = Unit2DMappedEndomorphism(data=other_data)
composed = endo.compose(endo2)
API Reference
Core Classes
MappedUnitField
N-dimensional unit field with interpolation.
Parameters:
data(UnitArray): N+1 dimensional array of shape (*spatial_dims, N)interp_method(InterpMethod): Interpolation strategy (default: NEAREST_MANHATTAN)cache_size(int, optional): LRU cache size for single queries (default: 128)
Methods:
get_value(coords): Get value at single coordinateget_values(coords_array): Get values at multiple coordinateswith_interp_method(method): Create copy with different interpolation
Unit2DMappedEndomorphism
2D unit field endomorphism with optimized OpenCV backend.
Parameters:
data(UnitArray): 3-dimensional array of shape (H, W, 2)interp_method(InterpMethod): Interpolation strategycache_size(int, optional): LRU cache size
Methods:
get_value(coords): Get single coordinate valueget_values(coords_array): Get multiple coordinate valuesrasterize_mapping(width, height): Convert to pixel-space mappingremap(data): Remap arbitrary (H, W, J) arraycompose(other): Compose with another endomorphism
Interpolation Methods
from unitfield.core.enums import InterpMethod
# Available methods:
InterpMethod.NEAREST_MANHATTAN # Nearest neighbor (Manhattan distance)
InterpMethod.NEAREST_EUCLIDEAN # Nearest neighbor (Euclidean distance)
InterpMethod.LINEAR # Linear/bilinear interpolation
InterpMethod.CUBIC # Cubic/bicubic interpolation
InterpMethod.LANCZOS4 # Lanczos-4 interpolation
Utility Functions
remap_tensor_cv2
Remap arbitrary tensors using pixel-space mappings.
from unitfield.core.unitfield import remap_tensor_cv2
result = remap_tensor_cv2(
data=tensor,
mapping=pixel_mapping,
interpolation=cv2.INTER_LINEAR,
border_mode=cv2.BORDER_REPLICATE,
border_value=0.0
)
Coordinate System
UnitField operates in unit space where coordinates are in the range [0, 1]:
0.0represents the start of each dimension1.0represents the end of each dimension- Coordinates are automatically scaled to array indices
Coordinate Constraints and Behavior
Important Limitations:
-
Infinite and NaN coordinates are NOT supported and will produce undefined behavior. This is by design to keep the functions simple and avoid overhead:
# ❌ AVOID - undefined behavior field.get_value((np.inf, 0.5)) field.get_value((np.nan, 0.5))
-
Out-of-bounds coordinates (< 0 or > 1) are handled via clipping to [0, 1] range:
# ✓ OK - will be clipped to valid range field.get_value((-0.5, 1.5)) # Treated as (0.0, 1.0)
-
Why this design?
- Unit field transformations are intended for normalized coordinate spaces
- Checking for inf/NaN on every coordinate adds unnecessary overhead
- Out-of-bounds handling beyond [0, 1] is simple to implement externally if needed
- Keeps the core functions fast and focused
Best Practices:
- Validate coordinates before passing to UnitField methods if they may contain special values
- For out-of-bounds behavior beyond simple clipping, preprocess coordinates externally
Examples
Creating Different Field Types
# 1D field
data_1d = np.linspace(0, 1, 100).reshape(-1, 1)
field_1d = MappedUnitField(data=data_1d, interp_method=InterpMethod.LINEAR)
# 3D field
data_3d = np.random.rand(10, 10, 10, 3)
field_3d = MappedUnitField(data=data_3d, interp_method=InterpMethod.CUBIC)
Switching Interpolation Methods
# Create field with one method
field = MappedUnitField(data=data, interp_method=InterpMethod.LINEAR)
# Switch to another method
cubic_field = field.with_interp_method(InterpMethod.CUBIC)
Batch Processing
# Process large batches efficiently
batch_size = 1000
coords = np.random.rand(batch_size, 2)
results = field.get_values(coords)
Image Warping Example
import numpy as np
import cv2
from unitfield.core.unitfield import Unit2DMappedEndomorphism
# Create a simple distortion field (barrel distortion)
h, w = 256, 256
y, x = np.ogrid[:h, :w]
center_x, center_y = w / 2, h / 2
# Calculate distance from center
dx = (x - center_x) / center_x
dy = (y - center_y) / center_y
r = np.sqrt(dx**2 + dy**2)
# Apply barrel distortion
distortion = 1 + 0.3 * r**2
new_x = center_x + dx * distortion * center_x
new_y = center_y + dy * distortion * center_y
# Normalize to unit space
unit_x = new_x / (w - 1)
unit_y = new_y / (h - 1)
distortion_field = np.stack([unit_x, unit_y], axis=-1).astype(np.float32)
# Create endomorphism and apply
endo = Unit2DMappedEndomorphism(data=distortion_field)
image = cv2.imread('input.jpg')
warped = endo.remap(image)
cv2.imwrite('output.jpg', warped)
Performance Tips
- Use caching for repeated queries: Set appropriate
cache_sizewhen creating fields - Batch operations: Use
get_values()instead of multipleget_value()calls - Choose the right backend: Use
Unit2DMappedEndomorphismfor 2D operations (faster via OpenCV) - Appropriate interpolation: Nearest neighbor is fastest, cubic/Lanczos are slower but smoother
Development
Running Tests
pip install pytest pytest-benchmark
pytest tests/ -v
Code Style
This project follows modern Python conventions:
- PEP 8 style guide
- Type hints throughout
- Comprehensive docstrings (Google style)
Known Limitations
- Inf/NaN coordinates: Not supported in remapping functions (see Coordinate Constraints section)
- Memory usage: Large N-dimensional fields may consume significant memory
- 2D optimization: Only 2D endomorphisms benefit from OpenCV backend optimization
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Citation
If you use UnitField in your research, please cite:
@software{unitfield2025,
author = {GrayJou},
title = {UnitField: N-dimensional Unit Field Transformations},
year = {2025},
url = {https://github.com/Grayjou/UnitField}
}
Acknowledgments
- Built with NumPy and OpenCV
- Inspired by coordinate transformation needs in computer vision and graphics
Support
For issues, questions, or contributions, please visit:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file unitfield-0.1.2.tar.gz.
File metadata
- Download URL: unitfield-0.1.2.tar.gz
- Upload date:
- Size: 32.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aac56f8b29ce937079fc08ff0b1e4c5ccec6090887cf02d24404f040c2af70e8
|
|
| MD5 |
5f635bf89fc7542f31e5d367c4bbccd8
|
|
| BLAKE2b-256 |
993b4ad3b8f8f9eee644b997c725aae3c921fe63b5261eadcf3b8d7a9e070384
|
File details
Details for the file unitfield-0.1.2-py3-none-any.whl.
File metadata
- Download URL: unitfield-0.1.2-py3-none-any.whl
- Upload date:
- Size: 18.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a81ae991c036d723afc9e1235f2d252d2c8e85110d91ace5a1d17d5e7df56f6
|
|
| MD5 |
ef2fd0efee3654f18de939130de79efd
|
|
| BLAKE2b-256 |
cb168d96c0f26beb2fa3a03fbdf4646d474c430cf77111823be78f12b75f65b6
|