Skip to content

Commit

Permalink
updating pypi publishing
Browse files Browse the repository at this point in the history
  • Loading branch information
Filimoa committed Dec 7, 2024
1 parent 84d8482 commit b75e83d
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 75 deletions.
16 changes: 3 additions & 13 deletions .github/workflows/publish_to_pypi.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
name: CI

on:
push:
branches:
- main
- master
tags:
- '*'
paths-ignore:
- '**/*.md'
pull_request:
workflow_dispatch:
release:
types: [published]

concurrency:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}

cancel-in-progress: true

permissions:
Expand Down
105 changes: 54 additions & 51 deletions README.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions polars_h3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
origin_to_directed_edges,
)
from .core.indexing import (
cell_to_boundary,
cell_to_lat,
cell_to_latlng,
cell_to_lng,
Expand Down Expand Up @@ -65,6 +66,7 @@
"cell_to_latlng",
"cell_to_local_ij",
"local_ij_to_cell",
"cell_to_boundary",
"get_resolution",
"str_to_int",
"int_to_str",
Expand Down
41 changes: 41 additions & 0 deletions polars_h3/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,3 +372,44 @@ def local_ij_to_cell(
plugin_path=LIB,
function_name="local_ij_to_cell",
)


def cell_to_boundary(cell: IntoExprColumn) -> pl.Expr:
"""
Retrieve the polygon boundary coordinates of the given H3 cell.
This function computes the vertices of the H3 cell's polygon boundary and returns them as a list of alternating latitude and longitude values. The coordinate list is structured as: `[lat0, lng0, lat1, lng1, ..., latN, lngN]`.
#### Parameters
- `cell`: IntoExprColumn
Column or expression containing H3 cell indices (as `pl.UInt64`, `pl.Int64`, or `pl.Utf8`).
#### Returns
Expr
A `pl.Expr` returning a list of `Float64` values representing the boundary vertices
of the cell in latitude-longitude pairs.
#### Examples
```python
>>> df = pl.DataFrame({
... "cell": ["8a1fb464492ffff"]
... })
>>> df.select(polars_h3.cell_to_boundary("cell"))
shape: (1, 1)
┌────────────────────────────────────┐
│ cell_to_boundary │
│ --- │
│ list[f64] │
╞════════════════════════════════════╡
│ [[50.99, -76.05], [48.29, -81.91...│
└────────────────────────────────────┘
#### Errors
- `ComputeError`: If null or invalid H3 cell indices are encountered.
"""
return register_plugin_function(
args=[cell],
plugin_path=LIB,
function_name="cell_to_boundary",
is_elementwise=True,
)
2 changes: 1 addition & 1 deletion polars_h3/core/inspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ def child_pos_to_cell(

def compact_cells(cells: IntoExprColumn) -> pl.Expr:
"""
Compact a set of H3 cells into a minimal covering set.
Compact a set of H3 cells into a minimal covering set. See [H3 documentation](https://h3geo.org/docs/highlights/indexing) for more details.
#### Parameters
- `cells`: IntoExprColumn
Expand Down
23 changes: 23 additions & 0 deletions src/engine/indexing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,26 @@ pub fn cell_to_latlng(cell_series: &Series) -> PolarsResult<Series> {

Ok(coords.into_series())
}

pub fn cell_to_boundary(cell_series: &Series) -> PolarsResult<Series> {
use crate::engine::utils::parse_cell_indices;
let cells = parse_cell_indices(cell_series)?;

let coords: ListChunked = cells
.into_par_iter()
.map(|cell| {
cell.map(|idx| {
let boundary = idx.boundary();
// Convert boundary vertices into a flat Vec<f64> of [lat, lng, lat, lng, ...]
let mut latlngs = Vec::with_capacity(boundary.len() * 2);
for vertex in boundary.iter() {
latlngs.push(vertex.lat());
latlngs.push(vertex.lng());
}
Series::new(PlSmallStr::from(""), &latlngs)
})
})
.collect();

Ok(coords.into_series())
}
6 changes: 6 additions & 0 deletions src/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ fn cell_to_latlng(inputs: &[Series]) -> PolarsResult<Series> {
crate::engine::indexing::cell_to_latlng(cell_series)
}

#[polars_expr(output_type_func=boundary_list_dtype)]
fn cell_to_boundary(inputs: &[Series]) -> PolarsResult<Series> {
let cell_series = &inputs[0];
crate::engine::indexing::cell_to_boundary(cell_series)
}

// ===== Inspection ===== //

#[polars_expr(output_type=UInt8)]
Expand Down
59 changes: 59 additions & 0 deletions tests/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,62 @@ def test_cell_to_latlng(test_params):
)
assert pytest.approx(df["lat"][0], 0.00001) == test_params["output_lat"]
assert pytest.approx(df["lng"][0], 0.00001) == test_params["output_lng"]


@pytest.mark.parametrize(
"test_params",
[
pytest.param(
{
"input": "8a1fb464492ffff",
"output_boundary": [
(48.853925897310056, 2.3725526996968154),
(48.853762357995556, 2.371650760662443),
(48.85311886121302, 2.3714610612212152),
(48.85263890985581, 2.3721732876265516),
(48.85280245093953, 2.3730752066146477),
(48.85344594161119, 2.3732649192433906),
],
},
id="case_string_paris",
),
pytest.param(
{
"input": "812bbffffffffff",
"output_boundary": [
(50.99021068384578, -76.05772874399094),
(48.295316381881364, -81.91962699890831),
(43.86011974432308, -80.98225290216081),
(42.02956371225369, -75.33345172379178),
(44.27784933847793, -69.95506755076666),
(48.757431677563375, -69.71947899952944),
],
},
id="case_string_large",
),
pytest.param(
{
"input": 581734010070237183,
"output_boundary": [
(50.99021068384578, -76.05772874399094),
(48.295316381881364, -81.91962699890831),
(43.86011974432308, -80.98225290216081),
(42.02956371225369, -75.33345172379178),
(44.27784933847793, -69.95506755076666),
(48.757431677563375, -69.71947899952944),
],
},
id="case_int_large",
),
],
)
def test_cell_to_boundary_known(test_params):
df = pl.DataFrame({"cell": [test_params["input"]]}).with_columns(
boundary=polars_h3.cell_to_boundary("cell")
)
boundary = df["boundary"][0]
for i, (exp_lat, exp_lng) in enumerate(test_params["output_boundary"]):
lat = boundary[i * 2]
lng = boundary[i * 2 + 1]
assert pytest.approx(lat, abs=1e-7) == exp_lat
assert pytest.approx(lng, abs=1e-7) == exp_lng
18 changes: 8 additions & 10 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b75e83d

Please sign in to comment.