-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
interactive plotting with
lonboard
(#67)
* draft of the explore functionality based on `lonboard` * expose the draft * docstring for `explore` * use the proper import from `matplotlib` for the standard normalizer * use `pandas` to compute the half range * specify `vmin` and `vmax` * explicitly specify `skipna` * refactor to construct the polygons as geoarrow This has speed implications: before, we've been using the shapely → geopandas → geoarrow route, which adds significant overhead. Co-authored-by: Kyle Barron <[email protected]> * allow choosing the transparency * move the healpix-specific code to `xdggs.healpix` In the future, we might want to move the conversion code to a separate module. * change the signature of `cell_boundaries` * also have h3 support the geoarrow cell boundaries * fix several typos * adjust the tests to fit the new dateline fix algorithm * update the list of extra dependencies for `explore` * mention that this only works for 1D arrays for now * add optional dependencies for `explore` * explicitly use `pyproj` to construct the crs string * raise an error if the geometry type is wrong * wrap the output of `crs.to_json()` in a json dict * verify that both backends produce the same polygons * move the data normalization to a separate function * move the table creation to a separate function * check that the normalization works properly * coverage configuration * pass on `center` to the normalizing function * skip the plotting module if `arro3.core` is not available * use `json` to construct the arrow extension metadata * Revert "skip the plotting module if `arro3.core` is not available" This reverts commit 5a71559. * workaround for missing macos-arm packages of arro3-core * install arro3-core using `pip` * always include the cell ids in the table data closes keewis#1 --------- Co-authored-by: Kyle Barron <[email protected]>
- Loading branch information
1 parent
b3b5a40
commit 774821d
Showing
12 changed files
with
408 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import numpy as np | ||
|
||
|
||
def create_arrow_table(polygons, arr, coords=None): | ||
from arro3.core import Array, ChunkedArray, Schema, Table | ||
|
||
if coords is None: | ||
coords = ["latitude", "longitude"] | ||
|
||
array = Array.from_arrow(polygons) | ||
name = arr.name or "data" | ||
arrow_arrays = { | ||
"geometry": array, | ||
"cell_ids": ChunkedArray([Array.from_numpy(arr.coords["cell_ids"])]), | ||
name: ChunkedArray([Array.from_numpy(arr.data)]), | ||
} | { | ||
coord: ChunkedArray([Array.from_numpy(arr.coords[coord].data)]) | ||
for coord in coords | ||
if coord in arr.coords | ||
} | ||
|
||
fields = [array.field.with_name(name) for name, array in arrow_arrays.items()] | ||
schema = Schema(fields) | ||
|
||
return Table.from_arrays(list(arrow_arrays.values()), schema=schema) | ||
|
||
|
||
def normalize(var, center=None): | ||
from matplotlib.colors import CenteredNorm, Normalize | ||
|
||
if center is None: | ||
vmin = var.min(skipna=True) | ||
vmax = var.max(skipna=True) | ||
normalizer = Normalize(vmin=vmin, vmax=vmax) | ||
else: | ||
halfrange = np.abs(var - center).max(skipna=True) | ||
normalizer = CenteredNorm(vcenter=center, halfrange=halfrange) | ||
|
||
return normalizer(var.data) | ||
|
||
|
||
def explore( | ||
arr, | ||
cell_dim="cells", | ||
cmap="viridis", | ||
center=None, | ||
alpha=None, | ||
): | ||
import lonboard | ||
from lonboard import SolidPolygonLayer | ||
from lonboard.colormap import apply_continuous_cmap | ||
from matplotlib import colormaps | ||
|
||
if len(arr.dims) != 1 or cell_dim not in arr.dims: | ||
raise ValueError( | ||
f"exploration only works with a single dimension ('{cell_dim}')" | ||
) | ||
|
||
cell_ids = arr.dggs.coord.data | ||
grid_info = arr.dggs.grid_info | ||
|
||
polygons = grid_info.cell_boundaries(cell_ids, backend="geoarrow") | ||
|
||
normalized_data = normalize(arr.variable, center=center) | ||
|
||
colormap = colormaps[cmap] | ||
colors = apply_continuous_cmap(normalized_data, colormap, alpha=alpha) | ||
|
||
table = create_arrow_table(polygons, arr) | ||
layer = SolidPolygonLayer(table=table, filled=True, get_fill_color=colors) | ||
|
||
return lonboard.Map(layer) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,12 @@ | ||
import geoarrow.pyarrow as ga | ||
import shapely | ||
|
||
from xdggs.tests.matchers import ( # noqa: F401 | ||
Match, | ||
MatchResult, | ||
assert_exceptions_equal, | ||
) | ||
|
||
|
||
def geoarrow_to_shapely(arr): | ||
return shapely.from_wkb(ga.as_wkb(arr)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.