Skip to main content

Pure Rust geospatial data abstraction library - Python bindings

Project description

OxiGDAL Python Bindings

PyPI version Python versions License

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 opened
  • ValueError: 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 path
  • width: Width in pixels
  • height: Height in pixels
  • bands: 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 path
  • dst_path: Destination raster path
  • dst_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 path
  • data: GeoJSON data as dictionary
  • pretty: Pretty-print JSON (default: True)

buffer_geometry(geometry: dict, distance: float, segments: int = 8) -> dict

Buffers a geometry by specified distance.

Parameters:

  • geometry: GeoJSON geometry
  • distance: Buffer distance in geometry units
  • segments: 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 pixels
  • height: Height in pixels
  • band_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 errors
  • ValueError: Invalid parameters or data
  • NotImplementedError: Unsupported operations
  • RuntimeError: Internal errors

Data Types

Supported raster data types:

  • uint8, int8
  • uint16, int16
  • uint32, int32
  • uint64, int64
  • float32, float64
  • complex64, 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

  1. Use context managers for automatic resource cleanup
  2. Batch operations when processing multiple files
  3. Use appropriate data types - smaller types use less memory
  4. Leverage NumPy for array operations
  5. Use resampling wisely - "nearest" is fastest, "lanczos" highest quality

Examples

See the examples/ directory for complete examples:

  • raster_processing.py - Raster I/O and processing
  • ndvi_calculation.py - Vegetation index calculation
  • reprojection.py - Coordinate transformation
  • vector_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

  • Built with PyO3 for Rust-Python bindings
  • Uses maturin for packaging
  • Inspired by GDAL but pure Rust

Support

Related Projects

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

oxigdal-0.1.1.tar.gz (847.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

oxigdal-0.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (899.9 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

oxigdal-0.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (860.1 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

oxigdal-0.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (864.7 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

oxigdal-0.1.1-cp39-abi3-win_amd64.whl (799.5 kB view details)

Uploaded CPython 3.9+Windows x86-64

oxigdal-0.1.1-cp39-abi3-manylinux_2_35_x86_64.whl (811.8 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.35+ x86-64

oxigdal-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (907.0 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

oxigdal-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (865.1 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

oxigdal-0.1.1-cp39-abi3-macosx_11_0_arm64.whl (714.5 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

oxigdal-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl (893.1 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file oxigdal-0.1.1.tar.gz.

File metadata

  • Download URL: oxigdal-0.1.1.tar.gz
  • Upload date:
  • Size: 847.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.8.7

File hashes

Hashes for oxigdal-0.1.1.tar.gz
Algorithm Hash digest
SHA256 873b579425097979f60c3320277c1989d62845b1e20379bcebccba86207114b7
MD5 608005d9ffd0ae3122b0c5cdfd4c5184
BLAKE2b-256 f6046550568b182227e80e5ae80561ef32d70f7df5263572003ebdd1f913e82b

See more details on using hashes here.

File details

Details for the file oxigdal-0.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 be1fa954ecee373ce8741d5c9f4d2552e3a8651eeacea02bdb971b3e402863b3
MD5 4399f0eca087a994ce046b914bb54a46
BLAKE2b-256 b69d5ebd27f3ef5bf52ed9bb9d9e6f9c16166e5cd99e504eb086bdac849450c1

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: pypi-publish.yml on cool-japan/oxigdal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxigdal-0.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f2581fd4a71038297a22c098458b1004d90e5cc52df32ab6737c98e40fa7c0f3
MD5 c45fec82bc45a74da473aa68f7c990a0
BLAKE2b-256 dd024e47cbdfbaf63258e6de508aaba0ea8b2596aaace20ef9a7162d43dd87cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: pypi-publish.yml on cool-japan/oxigdal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxigdal-0.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f924d29409ca6df0ac5e680d668eaeb818c9ca747f5e65bc1b3b470a11ecd06b
MD5 824281cef972e82321c3a60bb3626a13
BLAKE2b-256 6bb2cfd93a37ec68e10ad9e8282dad851ab125b5003471d711968dbb333a141f

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: pypi-publish.yml on cool-japan/oxigdal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxigdal-0.1.1-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: oxigdal-0.1.1-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 799.5 kB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for oxigdal-0.1.1-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 d1a70e0fd806b418c99c9b464b922fec893b4f4fec15ea2c6131e2d4147dfb5c
MD5 9eb495c4a27a0b1042ca840da4c222aa
BLAKE2b-256 87cabb9af9c725f8bf9c58afc5e413251f1f62e2927ca169e256c577df8179a6

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.1-cp39-abi3-win_amd64.whl:

Publisher: pypi-publish.yml on cool-japan/oxigdal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxigdal-0.1.1-cp39-abi3-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.1-cp39-abi3-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 8d30e7b7193aed1133740537e5bced4f36d390b16b7695cb3498cf1f9ea220ca
MD5 fbfa93e747f40d7128f743ba508db9e5
BLAKE2b-256 7aa252a031b2672b602a62e87abb9001a72df99316d4d7ce7b06de3be7a18ba8

See more details on using hashes here.

File details

Details for the file oxigdal-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2d57280008eebb51bfc90a096b4a5eddeb73c97f20703a8ccbc4bd87dfab11ab
MD5 b7224f7f52e8705ef9a0f747f51e0d99
BLAKE2b-256 9e42c215ee944ccdb5ef6f44de2db41e488f8e2b9f91ce9eca533d90a715c1fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: pypi-publish.yml on cool-japan/oxigdal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxigdal-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f67dab9a1d5e89e4b0bba5ce294dc15d573cda461adb4cb7424212c828046987
MD5 7d0932560333fc3a619fedbfeb5f98d8
BLAKE2b-256 de6216b14eef3c4ce19b2851e81675a99c2228d610f390766283d889f8244df9

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: pypi-publish.yml on cool-japan/oxigdal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxigdal-0.1.1-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.1-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8181f07fb96203f854efea1a751548404310e687c282337d340b45c0e23107da
MD5 d0e76f4456f7358ac06c0832075e1f89
BLAKE2b-256 ddbaa5292f584eae692fb3b35ff343472bc8339313ad95ef86aa12c1e4c796c0

See more details on using hashes here.

File details

Details for the file oxigdal-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 42be9a3d66fae4a05842096915934d726818f4964306259ca0d121c28b020570
MD5 e71434e71beb8fe11789ee221b98fe19
BLAKE2b-256 13cb74260c676dd3e871daf1c4e77a0b6e6b2244115fba6d0e9d0448e6601055

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: pypi-publish.yml on cool-japan/oxigdal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page