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.0.tar.gz (847.8 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.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (894.9 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

oxigdal-0.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (850.5 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

oxigdal-0.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (854.9 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

oxigdal-0.1.0-cp39-abi3-win_amd64.whl (795.7 kB view details)

Uploaded CPython 3.9+Windows x86-64

oxigdal-0.1.0-cp39-abi3-manylinux_2_35_x86_64.whl (811.9 kB view details)

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

oxigdal-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (902.9 kB view details)

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

oxigdal-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (856.0 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

oxigdal-0.1.0-cp39-abi3-macosx_11_0_arm64.whl (714.7 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

oxigdal-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl (889.3 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

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

File metadata

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

File hashes

Hashes for oxigdal-0.1.0.tar.gz
Algorithm Hash digest
SHA256 042ce066c921bbf2a67022543633c08a23cb6ce9424e70cfaa949eaedd41b3a1
MD5 c9959259bc4b23b438863da719c6c50b
BLAKE2b-256 cb9de710f5149199f5213ee26f833346b6728588d45b248e97356d1dfaeea5e1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for oxigdal-0.1.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d31ab0870fcf2b6c6dde7e8c7a1db4aba7aeecdcbe47f887a0bc6b6609a3107d
MD5 78795fdde93df526bbc25227d9d3c4c5
BLAKE2b-256 b938b4e8a522b2fde8c6061edb287cb4e25ecc560e6cbc8b89e632cc79c66d5e

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.0-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.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 d3638fb408cbb1b63572aaa935b92d60f9027edc4a0c5b9fd07fa9bf79d5d97f
MD5 cdd15b589ca50b4ba8fcd7ad71f30b3d
BLAKE2b-256 86e76e93c6d678850e959d1b55ffc4e168f25db74b63a6b44fd2f0355366b458

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.0-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.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 bd636a8d31df0a63d734b24878b531a981d4e5984cc3065dea17b7ce24217bd2
MD5 2d17ac9e9d4d5e952885046cd4ff3b5b
BLAKE2b-256 1d8383bbb1b2cf3e8ba2e5566ff7b29b554c06709af0ac2ee82a99e50e51ef38

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.0-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.0-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: oxigdal-0.1.0-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 795.7 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.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 43ee79b82eb8c0027669790eae39b16824dbf34bef27c67d38ced5f82459d335
MD5 ae4cb8c6a08b2d34366f7da48ccc12ec
BLAKE2b-256 7c1b090e5aa051f81667d21b9aa5cff7bc32c6bbcfb8a346e50ceb090e69c31d

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.0-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.0-cp39-abi3-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.0-cp39-abi3-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 d082247e95d5da460ae9e646ef94410f311c4f024ebe2a4d562359fa9ab09005
MD5 8153742f60c7bb9e801b5769a774d904
BLAKE2b-256 658774fc1e549214637d7d8bad61bea3e4921765aebcfb7e10d8abeeba58d638

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for oxigdal-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4def1065e019076825c35be3529129ed1cedc95f6c4d834a07893e6fcbee3c68
MD5 fd1cb273b26e3710f5f074e7b9f53e64
BLAKE2b-256 82bd8ff7681c15e6099019dfd77e1193fafc94a7d0c1409410b1a4f9c98bd3f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.0-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.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 50c9719dff50d0530e98bfc4151629cacf4f267d12e1ad921528d318aea94211
MD5 f3eb1e1ea27a7db57d3b5416485ff9a8
BLAKE2b-256 17b4ad7ac5c9f3c20ed91ba9bc5d7ea1228ecc9b3ad39ca298097945fbdf2a1c

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.0-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.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for oxigdal-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3d0465482ec9bc686b1e074866ac0d06c1d0001688c2bca4956e4701c1d9100b
MD5 613e41c79f986edd5eb3ab9eba7560c2
BLAKE2b-256 26cf30c97653088c0c44241cda16619e7b711615ad4d4c9e0f8a25f9914228b4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for oxigdal-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 0d2754527f279a0bccd529212e1f21f7b8e7ec7af861d731531118abbb0b3a78
MD5 624b916e0b52c85d863a5415c48c430f
BLAKE2b-256 6d42929d99501157da80b7ae38d500624478bafa5b98b27bd912ca49da2760cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxigdal-0.1.0-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