Pure Rust geospatial data abstraction library - Python bindings
Project description
OxiGDAL Python Bindings
Python bindings for OxiGDAL, a pure Rust geospatial data abstraction library. OxiGDAL provides high-performance geospatial operations with seamless NumPy integration.
Features
- Pure Rust Performance: Leverages Rust's speed and safety
- NumPy Integration: Zero-copy data transfer where possible
- Raster Operations: Read/write GeoTIFF, Zarr, NetCDF, and more
- Vector Operations: GeoJSON support with geometry operations
- Raster Calculator: Algebraic expressions on raster data
- Coordinate Transformations: Reprojection and warping
- Type Hints: Full type stub support for IDEs
- No External Dependencies: No GDAL installation required
Installation
From PyPI (recommended)
pip install oxigdal
From Source
# Install maturin
pip install maturin
# Build and install
cd crates/oxigdal-python
maturin develop --release
Quick Start
Reading Rasters
import oxigdal
import numpy as np
# Open a raster file
ds = oxigdal.open("input.tif")
# Get metadata
print(f"Size: {ds.width}x{ds.height}")
print(f"Bands: {ds.band_count}")
# Read a band as NumPy array
band1 = ds.read_band(1)
print(band1.shape, band1.dtype)
# Get full metadata
metadata = ds.get_metadata()
print(metadata)
# Close dataset
ds.close()
Writing Rasters
import oxigdal
import numpy as np
# Create test data
data = np.random.rand(512, 512).astype(np.float32)
# Create a new raster
ds = oxigdal.create_raster(
"output.tif",
width=512,
height=512,
bands=1,
dtype="float32",
crs="EPSG:4326",
nodata=-9999.0
)
# Write data
ds.write_band(1, data)
# Set metadata
ds.set_metadata({
"crs": "EPSG:4326",
"nodata": -9999.0
})
# Close
ds.close()
Using Context Manager
import oxigdal
import numpy as np
# Automatically closes the dataset
with oxigdal.open("input.tif") as ds:
data = ds.read_band(1)
print(f"Mean: {data.mean():.2f}")
Raster Calculator
import oxigdal
import numpy as np
# Open multi-band image
ds = oxigdal.open("sentinel2.tif")
red = ds.read_band(3) # Red band
nir = ds.read_band(4) # NIR band
# Calculate NDVI using algebraic expression
ndvi = oxigdal.calc(
"(NIR - RED) / (NIR + RED)",
NIR=nir,
RED=red
)
# More complex expressions
evi = oxigdal.calc(
"2.5 * (NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1)",
NIR=nir,
RED=red,
BLUE=ds.read_band(2)
)
# Simple arithmetic
scaled = oxigdal.calc("A * 0.0001 - 0.1", A=red)
Reprojection
import oxigdal
# Reproject to Web Mercator
oxigdal.warp(
"input.tif",
"output_3857.tif",
dst_crs="EPSG:3857",
resampling="bilinear"
)
# Resize raster
oxigdal.warp(
"input.tif",
"output_resized.tif",
width=1024,
height=1024,
resampling="cubic"
)
# Reproject and resize
oxigdal.warp(
"input.tif",
"output.tif",
dst_crs="EPSG:4326",
width=2048,
height=2048,
resampling="lanczos"
)
Vector Operations
import oxigdal
# Read GeoJSON
features = oxigdal.read_geojson("input.geojson")
print(f"Features: {len(features['features'])}")
# Buffer a geometry
point = {
"type": "Point",
"coordinates": [0.0, 0.0]
}
buffered = oxigdal.buffer_geometry(point, distance=100.0)
# Write GeoJSON
output = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": buffered,
"properties": {"name": "Buffered Point"}
}
]
}
oxigdal.write_geojson("output.geojson", output, pretty=True)
API Reference
Core Functions
open(path: str, mode: str = "r") -> Dataset
Opens a geospatial dataset.
Parameters:
path: Path to file (local or remote URL)mode: Open mode - "r" for read (default), "w" for write
Returns: Opened Dataset object
Raises:
IOError: If file cannot be openedValueError: If format is not supported
version() -> str
Returns the OxiGDAL version string.
Raster Functions
create_raster(...) -> Dataset
Creates a new raster file.
Parameters:
path: Output file pathwidth: Width in pixelsheight: Height in pixelsbands: Number of bands (default: 1)dtype: Data type (default: "float32")crs: CRS as WKT or EPSG code (optional)nodata: NoData value (optional)
Returns: Created Dataset opened for writing
calc(expression: str, **arrays) -> np.ndarray
Raster calculator - evaluates expressions on raster data.
Parameters:
expression: Mathematical expression (e.g., "(A - B) / (A + B)")**arrays: Named NumPy arrays (A=array1, B=array2, etc.)
Returns: Result array
Supported Operators:
- Arithmetic:
+,-,*,/,**(power) - Comparison:
<,>,<=,>=,==,!= - Functions:
sqrt,abs,log,exp,sin,cos,tan
warp(...) -> None
Reprojects (warps) a raster to different CRS or resolution.
Parameters:
src_path: Source raster pathdst_path: Destination raster pathdst_crs: Target CRS (EPSG code or WKT, optional)width: Target width in pixels (optional)height: Target height in pixels (optional)resampling: Resampling method (default: "bilinear")- Options: "nearest", "bilinear", "cubic", "lanczos"
Vector Functions
read_geojson(path: str) -> dict
Reads a GeoJSON file.
Parameters:
path: Path to GeoJSON file
Returns: Parsed GeoJSON as dictionary
write_geojson(path: str, data: dict, pretty: bool = True) -> None
Writes a GeoJSON file.
Parameters:
path: Output pathdata: GeoJSON data as dictionarypretty: Pretty-print JSON (default: True)
buffer_geometry(geometry: dict, distance: float, segments: int = 8) -> dict
Buffers a geometry by specified distance.
Parameters:
geometry: GeoJSON geometrydistance: Buffer distance in geometry unitssegments: Number of segments per quadrant (default: 8)
Returns: Buffered geometry as GeoJSON
Dataset Class
Properties
path: Dataset file path (read-only)width: Width in pixels (read-only)height: Height in pixels (read-only)band_count: Number of bands (read-only)
Methods
read_band(band: int) -> np.ndarray
Reads a raster band as NumPy array.
Parameters:
band: Band number (1-indexed)
Returns: 2D NumPy array with shape (height, width)
write_band(band: int, array: np.ndarray) -> None
Writes a NumPy array to a raster band.
Parameters:
band: Band number (1-indexed)array: 2D NumPy array to write
get_metadata() -> dict
Returns dataset metadata as a dictionary.
set_metadata(metadata: dict) -> None
Sets dataset metadata.
Parameters:
metadata: Metadata dictionary
close() -> None
Closes the dataset and flushes pending writes.
RasterMetadata Class
Metadata container for raster datasets.
Parameters:
width: Width in pixelsheight: Height in pixelsband_count: Number of bands (default: 1)data_type: Data type as string (default: "float32")crs: CRS as WKT or EPSG code (optional)nodata: NoData value (optional)
Methods:
to_dict(): Converts to dictionary
Exceptions
OxiGdalError
Base exception for all OxiGDAL errors. Inherits from Exception.
Specific error types are mapped to appropriate Python exceptions:
IOError: File I/O errorsValueError: Invalid parameters or dataNotImplementedError: Unsupported operationsRuntimeError: Internal errors
Data Types
Supported raster data types:
uint8,int8uint16,int16uint32,int32uint64,int64float32,float64complex64,complex128
Supported Formats
Raster Formats
- GeoTIFF (
.tif,.tiff) - Cloud Optimized GeoTIFF (COG)
- Zarr (
.zarr) - NetCDF (
.nc)
Vector Formats
- GeoJSON (
.geojson,.json) - FlatGeobuf (
.fgb) - Shapefile (
.shp) - GeoParquet (
.parquet)
Performance Tips
- Use context managers for automatic resource cleanup
- Batch operations when processing multiple files
- Use appropriate data types - smaller types use less memory
- Leverage NumPy for array operations
- Use resampling wisely - "nearest" is fastest, "lanczos" highest quality
Examples
See the examples/ directory for complete examples:
raster_processing.py- Raster I/O and processingndvi_calculation.py- Vegetation index calculationreprojection.py- Coordinate transformationvector_operations.py- GeoJSON and geometry operations
Development
Requirements
- Rust: 1.70 or later
- Python: 3.9 or later
- PyO3: 0.24.x (automatically handled by Cargo)
- Maturin: For building Python wheels
Building from Source
# Install development dependencies
pip install maturin pytest pytest-cov mypy ruff
# Build in debug mode
maturin develop
# Build in release mode
maturin develop --release
# Run tests
pytest tests/
# Type checking
mypy python/oxigdal/
# Linting
ruff check python/
Build Configuration
The crate uses PyO3 with specific feature flags:
- Default features (
extension-module): For building Python extensions (.so/.dylib files) - Without extension-module: For Rust unit tests that need to initialize Python
The extension-module feature prevents linking to libpython (correct for Python extensions), but Rust unit tests need libpython to initialize the interpreter. See "Running Tests" section below for details.
Running Tests
Python Tests (Recommended)
# Run all tests
pytest tests/ -v
# Run with coverage
pytest tests/ --cov=oxigdal --cov-report=html
# Run specific test file
pytest tests/test_raster.py -v
Rust Unit Tests
The library uses PyO3 with the extension-module feature for building Python extensions. To run Rust unit tests, you need to build without this feature:
# Compile library (default - with extension-module)
cargo check -p oxigdal-python --lib
# Compile and run Rust unit tests (without extension-module)
cargo test -p oxigdal-python --no-default-features --features geotiff,geojson,algorithms
# Or using maturin
maturin develop && pytest tests/
Note: The extension-module feature is required for building the Python extension but prevents Rust unit tests from linking to libpython. This is a PyO3 design choice - Python-facing tests should use pytest, while Rust unit tests validate internal logic.
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
License
Licensed under the Apache License, Version 2.0. See LICENSE for details.
Citation
If you use OxiGDAL in your research, please cite:
@software{oxigdal2026,
title = {OxiGDAL: Pure Rust Geospatial Data Abstraction Library},
author = {{COOLJAPAN OU (Team Kitasan)}},
year = {2026},
url = {https://github.com/cool-japan/oxigdal}
}
Acknowledgments
Support
- Documentation: https://docs.rs/oxigdal
- Issue Tracker: https://github.com/cool-japan/oxigdal/issues
- Discussions: https://github.com/cool-japan/oxigdal/discussions
Related Projects
- OxiGDAL Core - Core Rust library
- OxiGDAL WASM - WebAssembly bindings
- OxiGDAL CLI - Command-line interface
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
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 oxigdal-0.1.4.tar.gz.
File metadata
- Download URL: oxigdal-0.1.4.tar.gz
- Upload date:
- Size: 1.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f610eaa7a99f5a905876a12ad47afefac353b1853647a9b85d1145ccea49c370
|
|
| MD5 |
371c513e2050f785bba813b448523c78
|
|
| BLAKE2b-256 |
4cd61a5a2941202d5f1daae0b8c1d62f0a3ccacb408ac0b2bf46be08fc1da062
|
Provenance
The following attestation bundles were made for oxigdal-0.1.4.tar.gz:
Publisher:
pypi-publish.yml on cool-japan/oxigdal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oxigdal-0.1.4.tar.gz -
Subject digest:
f610eaa7a99f5a905876a12ad47afefac353b1853647a9b85d1145ccea49c370 - Sigstore transparency entry: 1340472300
- Sigstore integration time:
-
Permalink:
cool-japan/oxigdal@4ddd460c2b0fe3219e196f050288ff993d562539 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/cool-japan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@4ddd460c2b0fe3219e196f050288ff993d562539 -
Trigger Event:
push
-
Statement type:
File details
Details for the file oxigdal-0.1.4-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: oxigdal-0.1.4-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 877.9 kB
- Tags: CPython 3.9+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa38678bc3f3e2d9f533ed29b08b89c783bff1bfd86a48abd969ee57d849ebc8
|
|
| MD5 |
3ccebcabeca27a77e53530d4f4407561
|
|
| BLAKE2b-256 |
56530ccc63ba62510464f57e92bba004b5ffeb92755422405b240f10b6a5909f
|
Provenance
The following attestation bundles were made for oxigdal-0.1.4-cp39-abi3-win_amd64.whl:
Publisher:
pypi-publish.yml on cool-japan/oxigdal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oxigdal-0.1.4-cp39-abi3-win_amd64.whl -
Subject digest:
fa38678bc3f3e2d9f533ed29b08b89c783bff1bfd86a48abd969ee57d849ebc8 - Sigstore transparency entry: 1340472314
- Sigstore integration time:
-
Permalink:
cool-japan/oxigdal@4ddd460c2b0fe3219e196f050288ff993d562539 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/cool-japan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@4ddd460c2b0fe3219e196f050288ff993d562539 -
Trigger Event:
push
-
Statement type:
File details
Details for the file oxigdal-0.1.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: oxigdal-0.1.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 978.7 kB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67245fc82a1a5f39d699aff9fa8638612e3208617f698a1ef0cef50c066cf3cc
|
|
| MD5 |
8c938b5cc30f91f867bccdb72b5ab823
|
|
| BLAKE2b-256 |
d703b948e58bbd54c7a3f2a3efd5a45cdf48d83b767f72a34b5e0d30b8aba0a7
|
Provenance
The following attestation bundles were made for oxigdal-0.1.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
pypi-publish.yml on cool-japan/oxigdal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oxigdal-0.1.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
67245fc82a1a5f39d699aff9fa8638612e3208617f698a1ef0cef50c066cf3cc - Sigstore transparency entry: 1340472327
- Sigstore integration time:
-
Permalink:
cool-japan/oxigdal@4ddd460c2b0fe3219e196f050288ff993d562539 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/cool-japan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@4ddd460c2b0fe3219e196f050288ff993d562539 -
Trigger Event:
push
-
Statement type:
File details
Details for the file oxigdal-0.1.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: oxigdal-0.1.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 940.6 kB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c24417260b66274e07e592db18ab496ba7bb3859dbfa1f3d35819e018273f2e
|
|
| MD5 |
6f1ad5d6b74debcd8e70edcf20ac6535
|
|
| BLAKE2b-256 |
2ecaa8e6b070f3b1c99f237233e41a60e0f8b77fb7f0429ef0ecfc0eb2db7bb8
|
Provenance
The following attestation bundles were made for oxigdal-0.1.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
pypi-publish.yml on cool-japan/oxigdal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oxigdal-0.1.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
7c24417260b66274e07e592db18ab496ba7bb3859dbfa1f3d35819e018273f2e - Sigstore transparency entry: 1340472305
- Sigstore integration time:
-
Permalink:
cool-japan/oxigdal@4ddd460c2b0fe3219e196f050288ff993d562539 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/cool-japan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@4ddd460c2b0fe3219e196f050288ff993d562539 -
Trigger Event:
push
-
Statement type:
File details
Details for the file oxigdal-0.1.4-cp39-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: oxigdal-0.1.4-cp39-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 893.9 kB
- Tags: CPython 3.9+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d033a192d06eed79ef0fcf88734c11169067605c8ffbceff6919649670bd730
|
|
| MD5 |
d02740adbe691c5821a7037d9a9ae7d5
|
|
| BLAKE2b-256 |
62083ca30ab09dbe20c42005c73e7f7768278eefbe9e50895e0c25f9e4eb5873
|
Provenance
The following attestation bundles were made for oxigdal-0.1.4-cp39-abi3-macosx_11_0_arm64.whl:
Publisher:
pypi-publish.yml on cool-japan/oxigdal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oxigdal-0.1.4-cp39-abi3-macosx_11_0_arm64.whl -
Subject digest:
6d033a192d06eed79ef0fcf88734c11169067605c8ffbceff6919649670bd730 - Sigstore transparency entry: 1340472319
- Sigstore integration time:
-
Permalink:
cool-japan/oxigdal@4ddd460c2b0fe3219e196f050288ff993d562539 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/cool-japan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@4ddd460c2b0fe3219e196f050288ff993d562539 -
Trigger Event:
push
-
Statement type:
File details
Details for the file oxigdal-0.1.4-cp39-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: oxigdal-0.1.4-cp39-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 961.8 kB
- Tags: CPython 3.9+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36f5f056507819cce36c8f88b3e812d7c98fefb013fe4eaf0a14e40c5d5a92cd
|
|
| MD5 |
b084d7e87764dcd9393b185dbad13fbd
|
|
| BLAKE2b-256 |
c69ca525574e4c1bd40327fda9a83232b4635d1db15406a4dbb7d94d825c54e5
|
Provenance
The following attestation bundles were made for oxigdal-0.1.4-cp39-abi3-macosx_10_12_x86_64.whl:
Publisher:
pypi-publish.yml on cool-japan/oxigdal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oxigdal-0.1.4-cp39-abi3-macosx_10_12_x86_64.whl -
Subject digest:
36f5f056507819cce36c8f88b3e812d7c98fefb013fe4eaf0a14e40c5d5a92cd - Sigstore transparency entry: 1340472334
- Sigstore integration time:
-
Permalink:
cool-japan/oxigdal@4ddd460c2b0fe3219e196f050288ff993d562539 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/cool-japan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@4ddd460c2b0fe3219e196f050288ff993d562539 -
Trigger Event:
push
-
Statement type: