Metadata-Version: 2.4
Name: daft-h3
Version: 0.1.0
Summary: H3 geospatial indexing functions for Daft
Author-email: Desmond Cheong <desmond@desmondcheong.com>, Garrett Weaver <gweaverdev@icloud.com>
Maintainer-email: Garrett Weaver <gweaverdev@icloud.com>
License-Expression: Apache-2.0
Project-URL: Repository, https://github.com/gweaverbiodev/daft-h3
Project-URL: Issues, https://github.com/gweaverbiodev/daft-h3/issues
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: daft>=0.7.5
Provides-Extra: test
Requires-Dist: pytest==9.0.3; extra == "test"
Requires-Dist: pytest-xdist==3.5.0; extra == "test"
Requires-Dist: build>=1.0; extra == "test"
Provides-Extra: dev
Requires-Dist: ruff==0.15.10; extra == "dev"
Requires-Dist: isort==8.0.1; extra == "dev"
Requires-Dist: mypy==1.20.0; extra == "dev"
Requires-Dist: pre-commit==4.5.1; extra == "dev"
Dynamic: license-file

# daft-h3

Native [H3](https://h3geo.org/) geospatial indexing functions for [Daft](https://github.com/Eventual-Inc/Daft).

## Installation

```bash
pip install daft-h3
```

## Usage

```python
import daft
import daft_h3
from daft import col
from daft.session import Session

sess = Session()
sess.load_extension(daft_h3)

with sess:
    df = daft.from_pydict({"lat": [37.7749, 48.8566], "lng": [-122.4194, 2.3522]})
    df = df.select(daft_h3.h3_latlng_to_cell(col("lat"), col("lng"), 7).alias("cell")).collect()
    df = df.select(daft_h3.h3_cell_to_str(col("cell")).alias("hex")).collect()
    df.show()
```

All cell-input functions accept both UInt64 and Utf8 (hex string) columns, so you can operate directly on string H3 data without an explicit conversion step. Functions that return cell indices preserve the input type: string in, string out.

For maximum throughput, convert to UInt64 once at the top of a pipeline with `h3_str_to_cell` and operate on integers throughout.

## Functions

| Function | Input | Output |
|---|---|---|
| `h3_latlng_to_cell` | lat (f64), lng (f64), resolution (0-15) | UInt64 |
| `h3_cell_to_lat` | cell (UInt64 or Utf8) | Float64 |
| `h3_cell_to_lng` | cell (UInt64 or Utf8) | Float64 |
| `h3_cell_to_str` | cell (UInt64 or Utf8) | Utf8 |
| `h3_str_to_cell` | hex (Utf8) | UInt64 |
| `h3_cell_resolution` | cell (UInt64 or Utf8) | UInt8 |
| `h3_cell_is_valid` | cell (UInt64 or Utf8) | Boolean |
| `h3_cell_parent` | cell (UInt64 or Utf8), resolution (0-15) | same as input |
| `h3_grid_distance` | a (UInt64 or Utf8), b (UInt64 or Utf8) | Int32 |

Invalid cell indices produce null. Resolution is validated at plan time.

## Performance

Benchmarked against wrapping the `h3` Python library in a `@daft.func.batch` UDF (1M rows, hex string columns, Apple M-series):

| Function | daft-h3 | UDF (h3-py) | Speedup |
|---|---|---|---|
| `latlng_to_cell` | 416ms | 1,407ms | **3.4x** |
| `cell_to_lat` | 242ms | 1,011ms | **4.2x** |
| `cell_parent` | 75ms | 1,072ms | **14.4x** |
| `cell_resolution` | 47ms | 767ms | **16.4x** |
| `str_to_cell` | 46ms | 756ms | **16.6x** |

## Development

```bash
git clone https://github.com/gweaverbiodev/daft-h3.git
cd daft-h3
uv sync --extra dev --extra test
make install-hooks
```

Requires Rust (stable), Python >= 3.10, and [uv](https://docs.astral.sh/uv/).

```bash
make install-hooks  # Install pre-commit git hooks
make lint           # Check formatting and types
make format         # Auto-fix and format
make test           # Run tests
```
