Bump org.locationtech.proj4j:proj4j from 1.3.0 to 1.4.1#23
Open
dependabot[bot] wants to merge 1 commit into
Open
Bump org.locationtech.proj4j:proj4j from 1.3.0 to 1.4.1#23dependabot[bot] wants to merge 1 commit into
dependabot[bot] wants to merge 1 commit into
Conversation
Bumps [org.locationtech.proj4j:proj4j](https://github.com/locationtech/proj4j) from 1.3.0 to 1.4.1. - [Release notes](https://github.com/locationtech/proj4j/releases) - [Changelog](https://github.com/locationtech/proj4j/blob/master/CHANGELOG.md) - [Commits](locationtech/proj4j@v1.3.0...v1.4.1) --- updated-dependencies: - dependency-name: org.locationtech.proj4j:proj4j dependency-version: 1.4.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
mjohns-databricks
pushed a commit
that referenced
this pull request
Jun 24, 2026
…sobands) Two render fixes for the H3-isobands notebook: 1. PIXEL_SIZE_DEG — added to params cell (#6) as ~3 px per hex edge at SF latitude (h3.average_hexagon_edge_length / 3 / cos-scaled degrees). Passed to rst_h3_gridspec(pixel_size=PIXEL_SIZE_DEG) in cell #18 so per-band tiles have solid hex footprints rather than scattered specks. 2. composite="depth" — stack render cell (#28) now calls plot_raster(..., composite="depth") to show coverage depth (0..N viridis gradient) instead of an RGB-of-presence-masks composite that reads mostly black. Markdown cell #27 updated to describe the coverage-depth view. Markdown cell #23 notes that the finer pixel size produces solid single-band footprints. No outputs (cluster-only notebook; outputs cleared). Co-authored-by: Isaac
mjohns-databricks
added a commit
that referenced
this pull request
Jun 24, 2026
…agrams (#42) * docs(spec): gbx.viz + pyrx escape-hatches design Design for a tier-agnostic gbx.viz module ([viz] extra: matplotlib + geopandas + folium + mapclassify) promoting the EO-series notebook helpers -- plot_raster / plot_file (decimation + 2-98% percentile stretch + nodata masking) and as_gdf / cells_as_gdf (Spark DF -> GeoDataFrame for .explore()) -- plus two Python-only pyrx escape-hatches (tile_to_numpy, generalized rst_apply). Drops generate_cells; keeps set_conf_safe + band-table ETL notebook-local. Pending user review. Co-authored-by: Isaac * docs(plan): gbx.viz + pyrx escape-hatches implementation plan Co-authored-by: Isaac * feat(viz): [viz] extra + package skeleton + dep guard Adds gbx.viz package (importable skeleton for later tasks), assert_viz_available() guard (raises ImportError with install hint if matplotlib/geopandas missing), and the [viz] optional-dependency extra in pyproject.toml. Pins matplotlib==3.10.9, geopandas==1.1.3, folium==0.20.0, mapclassify==2.10.0 in requirements-pyrx-ci.in (latest on corp proxy) and regenerates the hash-pinned lock (83 packages). 2 tests pass. Co-authored-by: Isaac * feat(viz): raster decimation + percentile-stretch pipeline Add _raster.py with _decimated_read, _needs_percentile_stretch, and _percentile_stretch helpers; test_raster.py with 3 TDD tests (3 passed). * feat(viz): plot_raster + plot_file public raster plotters Append _render, plot_raster, plot_file to viz/_raster.py; export from viz/__init__.py. Matplotlib/rasterio are lazy-imported inside each plotter; assert_viz_available() guards the public API. Agg backend forced when headless. Also fixes unused pytest import (F401) left from Task 2 and adds missing # noqa: E402 annotations so flake8 is fully clean for all viz files. Co-authored-by: Isaac * fix(viz): robust headless backend selection in _render Replace unreliable get_current_fig_manager() probe with a correct headless guard: select Agg before pyplot import only when pyplot has not yet been imported (no prior use() lock-in), MPLBACKEND is unset, and no display is present (DISPLAY/WAYLAND_DISPLAY absent). Databricks notebooks pre-import pyplot with their own backend, so they are never overridden. Co-authored-by: Isaac * feat(viz): as_gdf + cells_as_gdf Spark→GeoDataFrame adapters Adds viz._vector with as_gdf (WKT column → GeoDataFrame, EPSG:4326, max_rows guard with truncation warning) and cells_as_gdf (H3 bigint cell ids → boundary polygons via h3 v4 int_to_str + cell_to_boundary). Exports both from viz.__init__. 3/3 tests green. Co-authored-by: Isaac * feat(pyrx): tile_to_numpy + rst_apply escape-hatches Add two Python-only escape-hatches in pyrx/core/escape.py: - tile_to_numpy(tile_or_bytes): drops a collected tile or raw bytes to a numpy ndarray (all bands) for host-side exploration. - rst_apply(tile_col, fn, returnType): applies an arbitrary rasterio callable per-row via a dynamic @udf; null tile -> null. Both are re-exported on pyrx.functions (noqa: F401) so callers use `from databricks.labs.gbx.pyrx.functions import tile_to_numpy, rst_apply`. Neither is SQL-registered; binding-parity count is unchanged (154). Co-authored-by: Isaac * ci(viz): run test/viz in the lightweight tier (heavy skips) Add "viz" to _LIGHT_TEST_DIRS in test/conftest.py (heavy CI phase collect_ignore exclusion) and to the pytest dir list in the light CI action. Clean-venv verification against requirements-pyrx-ci.txt confirmed 829 passed, 2 skipped, RC=0 — all viz deps already in lock. Co-authored-by: Isaac * docs(viz): gbx.viz page + raster escape-hatches section Co-authored-by: Isaac * docs(viz): correct dev-container-match note in light lock comment Co-authored-by: Isaac * docs(eo-series): migrate notebooks onto gbx.viz + pyrx escape-hatches; drop library.py The gbx.viz module ([viz] extra) and the pyrx escape-hatches (rst_apply, tile_to_numpy) now provide, as first-class package APIs, the helpers the eo-series previously carried in a local library.py + config_nb defs. - config_nb.ipynb: install geobrix[light,stac,viz] (folium/mapclassify/geopandas now come via [viz], not a manual %pip); import plot_raster/plot_file/as_gdf/ cells_as_gdf from databricks.labs.gbx.viz and rst_apply/tile_to_numpy from pyrx.functions; drop the local as_gdf/cells_as_gdf defs and the `import library`; keep the one surviving constant (FILENAME_TIMESTAMP_FORMAT) inline. - library.py: DELETED. Everything in it is now superseded — plot_raster/plot_file by gbx.viz, to_numpy_arr/rasterio_lambda by tile_to_numpy/rst_apply, generate_cells was dead heavy-only, _set_conf_safe duplicated config_nb's set_conf_safe, FILE_SIZE_THRESHOLD was unused. - 01-04: call the package functions directly (plot_raster/plot_file, the bare FILENAME_TIMESTAMP_FORMAT). nb03's raster->timeseries projection moves from library.rasterio_lambda("tile.raster", fn) to rst_apply("tile", fn) — rst_apply takes the tile struct and opens tile["raster"] itself (not the raw bytes column). - README: drop the library.py row; note viz helpers come from gbx.viz; [light,stac,viz]. Source cells migrated; notebooks need re-execution on a cluster to refresh outputs (they read /Volumes and run on Serverless/classic, not locally). Co-authored-by: Isaac * docs(eo-series): executed notebooks on gbx.viz + cleaned config_nb Re-run on Serverless against the [viz]-enabled wheel. config_nb drops the now-dead imports (geopandas/matplotlib.pyplot/rasterio.MemoryFile/io.BytesIO — superseded by gbx.viz) and the library.py autoreload lines; installs geobrix[light,stac,viz]. Notebooks 01-04 carry refreshed outputs from the package-based viz/escape-hatch APIs. Co-authored-by: Isaac * docs(eo-series): refresh notebooks doc page + README for gbx.viz migration Bring docs/docs/notebooks/eo-series.mdx and the series README in line with the gbx.viz migration: drop all library.py references (file deleted), install geobrix[light,stac,viz] (+ the viz extras matplotlib/geopandas/folium/mapclassify), note visualization helpers come from databricks.labs.gbx.viz, and replace the raster->timeseries `rasterio_lambda` mention with the `rst_apply` escape-hatch. Option-2 (heavyweight) now flips only config_nb.ipynb. Co-authored-by: Isaac * docs(spec): H3 cell rasterizer (rst_h3_rasterize_agg + rst_h3_gridspec) design Design for a DGGS-cell rasterizer: rasterize a set of H3 cell ids (+ optional value) into a raster tile via pixel-centroid burn (the inverse of rst_h3_rastertogrid). Grouped aggregator rst_h3_rasterize_agg (heavy UDAF + light grouped pandas_udf, light SQL returns BINARY per the light-agg convention; default value = 1/NoData presence mask; default 4326 with optional projected srid + auto extent/pixel-size, full overrides). rst_h3_gridspec defines the complete SHARED grid/canvas (snapped origin + pixel size + dims + srid) once over the union of all thresholds, so every band rasterizes to a byte-identical transform and stacks cleanly via rst_frombands_agg (no half-pixel drift). Implemented as a scalar per-cell bbox + native min/max + snap (both tiers; avoids the grouped-pandas_udf struct-return limit). Quadbin/BNG variants are follow-ons. Validation: CI round-trip vs rastertogrid + partition property + a committed FCC fixed-wireless subset; DEM elevation-isoband notebook for the full polygons->polyfill->rasterize->stack demo. Pending user review. Co-authored-by: Isaac * docs(plan): H3 cell rasterizer implementation plan Co-authored-by: Isaac * feat(pyrx): H3 cell rasterize core (centroid burn + gridspec) Adds cellraster.py with pure-function rasterization primitives: _h3_str (signed-Long normalization), _resolution (uniform-res guard), cell_bbox, snap_bounds (lattice-aligned snapping, DRY helper for Task 2), compute_gridspec (kring-padded, snapped 8-tuple), and cells_to_raster (pixel-centroid burn to float64 GTiff bytes). 5/5 tests green. Note: brief's half-pixel centroid expansion pre-snap caused the single-cell kring_pad=0 case to straddle two lattice slots (→2x2); removed expansion — snap_bounds correctly gives 1x1 for a single point. * fix(pyrx): drop redundant H3 round-trip in cells_to_raster hot loop latlng_to_cell already returns canonical lowercase hex (same format as lut keys built via _h3_str); int_to_str(str_to_int(...)) is a no-op. Removing two calls per pixel from the hot path. Also adds a note to snap_bounds docstring that pixel_size is not included in its return tuple and must be threaded separately by callers. Co-authored-by: Isaac * feat(pyrx): gbx_h3_cell_bbox scalar + rst_h3_gridspec helper Adds the scalar gbx_h3_cell_bbox UDF (returns STRUCT<xmin,ymin,xmax,ymax> for one H3 cell with optional kring_pad neighbourhood expansion) and the rst_h3_gridspec() DataFrame helper (snapped shared canvas per group of H3 cells). Both are Serverless-safe: no spark.conf.set, no _jvm access, no sparkContext/rdd usage. The snap arithmetic in rst_h3_gridspec exactly mirrors cellraster.compute_gridspec (floor/ceil lattice alignment), verified by test_rst_h3_gridspec_matches_core. Co-authored-by: Michael Johns * fix(pyrx): rst_h3_gridspec auto-pixel-size parity + empty-input guard - Add test_rst_h3_gridspec_auto_pixel_size_matches_core: verifies that the pixel_size=None path (edge-length + lat-cosine formula) in the Spark helper produces width, height, xmin, ymin, and pixel_size within 1e-9 of cellraster.compute_gridspec. Test passes as-is — midlat derivation was already equivalent between the two paths. - Add test_rst_h3_gridspec_empty_raises: empty DataFrame with the right schema must raise ValueError("empty cell set"), mirroring the core. - Fix rst_h3_gridspec empty-input guard: was silently falling back to pixel_size=1.0 (via _res=None branch). Now raises ValueError immediately on first()=None, matching compute_gridspec's guard. Co-authored-by: Isaac * feat(pyrx): rst_h3_rasterize_agg grouped aggregator Adds _rst_h3_rasterize_agg_udf (pandas_udf, BinaryType), the public rst_h3_rasterize_agg Column wrapper (returns tile struct via _as_tile_udf), and registers gbx_rst_h3_rasterize_agg in _sql_aggregators. Presence-mask default (value omitted -> 1.0), explicit-extent path for aligned band stacking, Serverless-safe (no spark.conf/_jvm). 2 tests green. Co-authored-by: Isaac * refactor(pyrx): drop dead value-None branch in rst_h3_rasterize_agg udf Co-authored-by: Isaac * docs(function-info): register gbx_rst_h3_rasterize_agg + gbx_h3_cell_bbox Add both new H3-cell-rasterizer functions to the canonical registered list, doc SQL examples, function-info.json (regenerated), and binding- parity test. Also adds h3_/gbx_h3_ prefix to generate-function-info.py MODULES + PACKAGE_PREFIXES so the generator discovers h3_*_sql_example functions in rasterx_functions_sql.py. Binding-parity counts: Python 156, function-info 156, Scala 153 (the 2 new names are Scala-absent by design until Task 7 adds the JVM side). Co-authored-by: Isaac * fix(function-info): h3_cell_bbox SQL example args + rasterize_agg ordering - h3_cell_bbox_sql_example: add missing 4th arg kring_pad=0 to SQL call (registered UDF requires all 4 positional args: cellid, srid, mode, kring_pad); drop non-standard L long-literal suffixes from VALUES clause - registered_functions.txt (both copies): move gbx_rst_h3_rasterize_agg before gbx_rst_h3_rastertogridavg (alphabetical: 'rasterize_' < 'rastertogrid') - Regenerate function-info.json (156 entries) - Both doc-tests green; binding parity unchanged (Scala 153/156, known Task 7 gap) Co-authored-by: Isaac * test(pyrx): H3 rasterize round-trip + partition validation Add CI validation tests for rst_h3_rasterize_agg (T1-T4): - Round-trip: SRTM DEM -> gbx_rst_h3_rastertogridavg (LATERAL UDTF, band 1) -> cells_to_raster; >99% of burned pixels match cell measures. - Partition: polyfill polygon -> rasterize_agg; every pixel centroid burned <=> its h3 cell is in the input set (exact bijection). Uses LATERAL join for the light-tier UDTF (flat band/cellID/measure rows), not array[0] indexing which is the heavy-tier shape. * test(pyrx): sound nearest-value round-trip oracle + partition pixel-count bounds Fix 1: replace searchsorted-nearest (insertion-point, not nearest) with a correct two-neighbour min-distance check; widen atol from 1e-6 to 1e-3 to match float32 GeoTIFF quantization. 0/N pixels off against current impl. Fix 2: add burned_count lower/upper bounds after the biconditional loop so an all-NoData or all-burned tile cannot pass vacuously. Co-authored-by: Isaac * test(pyrx): FCC fixed-wireless H3 rasterize fixture + test Curates 400-row Miami-Dade (block_geoid 12086, provider 230008) subset from FCC BDC unlicensed fixed-wireless data; commits as test/pyrx/data/fcc_uflw_miamidade_subset.csv. Adds test_h3_rasterize_fcc.py: groupBy(provider, speed).agg(rst_h3_rasterize_agg) on real res-8 H3 cells, asserting >=1 burned pixel per tile. Co-authored-by: Isaac * test(pyrx): multi-speed-tier FCC fixture for the rasterize-per-threshold analog Previous fixture was homogeneous (all 25 Mbps, single provider), so the groupBy(provider, speed) produced only 1 tile. Re-curate to span 5 tiers (10, 25, 45, 100, 160 Mbps), 60 rows each, 6 distinct (provider, speed) groups, all from Miami-Dade block_geoid prefix 12086. Strengthen test to assert >= 4 distinct speed tiers in the loaded CSV and >= 4 tiles after aggregation, with per-tile burn-pixel assertion unchanged. Co-authored-by: Isaac * feat(rasterx): RST_H3_RasterizeAgg UDAF + gbx_h3_cell_bbox (heavy tier) Add the heavyweight Scala tier for the H3 cell rasterizer, closing the binding-parity gap left by the lightweight tier (Tasks 1-6): - RST_H3_RasterizeAgg: TypedImperativeAggregate that accumulates (cellId, value) pairs per group and, on eval, burns them into one GTiff tile by pixel-centroid mapping (the inverse of RST_H3_RasterToGrid's affine). Resolution is derived from the cells (errors on mixed); the grid is taken from an explicit extent when fully supplied, else snapped/lattice-aligned from the cell set + kring_pad (port of pyrx cellraster.compute_gridspec). NoData=-9999.0; a null value burns the 1.0 presence mask. Param order and semantics mirror the light rst_h3_rasterize_agg. - RST_H3_CellBBox (gbx_h3_cell_bbox): scalar returning STRUCT<xmin,ymin,xmax,ymax> from the cell centroid (centroids) or hexagon envelope (spatial_envelope), reprojected to srid, with optional kring_pad expansion. Mirrors the light _h3_cell_bbox_udf. - Register both in rasterx.functions + Column helpers; per-pixel and gridspec reprojection go through GDALManager-guarded OSR transforms. Test: RST_H3_RasterizeAggTest (7 tests, direct-execute, no Spark) asserts every covered pixel maps back into the input cell set, the presence mask, empty-group null, mixed-resolution error, serde roundtrip, and both cell-bbox modes. Binding parity 156/156. Co-authored-by: Isaac * test(rasterx): heavy<->light H3 rasterize parity (JAR-gated) Adds test_h3_rasterize_parity.py: rasterizes a res-9 H3 cell set onto the SAME explicit grid (from cellraster.compute_gridspec) via both tiers and asserts the covered-pixel masks are identical. Module-level skip when JAR is absent. Ran green (1 passed in 20.33s) after JAR rebuild. Co-authored-by: Isaac * feat(rasterx): heavy Python wrappers for rst_h3_rasterize_agg + gbx_h3_cell_bbox Add two Python wrappers to the heavy-tier rasterx/functions.py that were absent despite the underlying SQL functions being registered by the Scala UDAF (Task 7): - rst_h3_rasterize_agg(cellid, value, srid, pixel_size, xmin, ymin, xmax, ymax, width, height, mode, kring_pad) → calls gbx_rst_h3_rasterize_agg with all 12 positional args; mirrors the 12-arg pyrx light-tier signature. - gbx_h3_cell_bbox(cellid, srid=4326, mode="centroids", kring_pad=0) → calls gbx_h3_cell_bbox; matches the public name used by the pyrx light tier with the same optional-arg defaults. Update test_h3_rasterize_parity.py to invoke the new rx.rst_h3_rasterize_agg wrapper directly (previously bypassed via f.call_function), validating the wrapper end-to-end. Verified: 1 passed (parity test ran green with JAR), bindings 156/156, black/isort clean on both changed files (E501 suppressed project-wide). * style(test): black-normalize _LIGHT_TEST_DIRS list in conftest Pre-existing container-black noncompliance (host black left the long line); normalize so the CI lint gate stays green. Semantically identical. Co-authored-by: Isaac * docs(rasterx): rst_h3_rasterize_agg + gbx_h3_cell_bbox + rst_h3_gridspec Add three new entries to the RasterX function reference page: - rst_h3_rasterize_agg (Aggregator Functions): H3 cell-to-raster burn aggregator with full BINARY warning block and CodeFromTest reference. Inverse of rst_h3_rastertogrid*; cross-references rst_frombands_agg for band stacking. - gbx_h3_cell_bbox (Grid Functions H3): scalar bounding-box function for one H3 cell in the given CRS; drives the canvas extent params for rst_h3_rasterize_agg. - rst_h3_gridspec (Grid Functions H3): Python-only helper note explaining how to compute a shared snapped canvas for aligned multi-band stacking via rst_frombands_agg / rst_merge_agg. Also bumps section counts (Aggregators 6→7, H3 Grid 5→7) and adds rst_h3_rasterize_agg to the Overview bullet. Co-authored-by: Isaac * docs(notebooks): H3 cell rasterize + stacking demo (DEM isobands) Full pipeline example: SRTM DEM → elevation isobands → h3.polygon_to_cells polyfill → rst_h3_gridspec shared canvas → rst_h3_rasterize_agg per-band tiles → rst_frombands_agg multi-band stack → plot_raster visualization. Includes README with telco/coverage-analysis analogy and runtime instructions. Runs on Serverless (geobrix[light,viz] only, no JAR/GDAL init script). Co-authored-by: Isaac * docs(rasterx): correct rst_h3_gridspec API doc + reconcile spec snapping wording - Fix rst_h3_gridspec MDX entry: was claiming a non-existent signature `rx.rst_h3_gridspec(cellids, srid, mode, kring_pad)` returning a plain dict with width_px/height_px keys; replace with the real DataFrame helper signature (df, cell_col, *group_cols, srid, pixel_size, mode, kring_pad) and the actual STRUCT<xmin,ymin,xmax,ymax,pixel_size,width,height,srid> return type (matching _GRID_SCHEMA in pyrx/functions.py). - Correct the "both execution tiers" claim: rst_h3_gridspec is lightweight (pyrx) only; add a pointer to the gbx_h3_cell_bbox scalar + min/max aggregate recipe for heavyweight users. - Fix spec (2026-06-23-h3-cell-rasterizer-design.md): centroid-mode bounds description removed the "±half-pixel / land on pixel centers" sentence; replaced with the actual floor/ceil snap that shipped (matching the implementation in _snap_to_grid). Co-authored-by: Isaac * docs(rasterx): diagram + release-notes + tile-output/table for H3 rasterizer Fix three QC-judge failures blocking push: - diagram-coverage (D4a/D4b): add rst_h3_rasterize_agg to Aggregators card and bump all three "107 functions/SQL functions" strings to 108; re-render SVG + PNG - doc-coverage D4 (tile-output): rst_h3_rasterize_agg_sql_example_output changed from bare [BINARY] to {null, <raster bytes>, {driver -> GTiff, ...}} matching the tileDataType struct the UDAF returns - doc-coverage D5 (table-alignment): h3_cell_bbox_sql_example_output ASCII table re-aligned to canonical column widths (18 + 31 chars) - release-notes-functions: add bullet for gbx_rst_h3_rasterize_agg and gbx_h3_cell_bbox (+ rst_h3_gridspec light helper) under v0.4.0 Co-authored-by: Isaac * docs(notebooks): rename to h3_rasterize_isobands + auto-stage DEM cell Rename h3_rasterize_demo.ipynb -> h3_rasterize_isobands.ipynb. Add a "Stage the sample DEM" cell that idempotently downloads SRTM N40W073 from the public AWS Terrain Tiles dataset and writes it to DEM_PATH on first run — node-local temp + rasterio .hgt->GTiff (no gdal_translate CLI, Serverless-safe) + FUSE-safe shutil.copy to the Volume. Carries the user's path edits (geobrix[light,viz] wheel + DEM_PATH on the geospatial_docs sample-data Volume); README requirements updated to match (auto-staging, real paths). Co-authored-by: Isaac * fix(test): guard h3/rasterio/pandas imports in heavy<->light parity test The cross-tier parity test lives in test/rasterx (heavy-collected) but needs the light-tier deps (h3/rasterio/pandas via pyrx) in addition to the JAR. The heavy CI build python env has the JAR but not the light deps, so the module-top `import h3` errored at COLLECTION (ModuleNotFoundError), failing the heavy build. The dev container masked it (it has both tiers). Guard the light imports with pytest.importorskip so heavy CI skips the module cleanly; it still runs where the JAR + light deps coexist (dev container, cluster). Verified: collection with h3 blocked -> skipped (no error); flake8 clean. Co-authored-by: Isaac * feat(viz): grid_as_gdf canvas helper + cells_as_gdf dissolve_by Adds grid_as_gdf(grid, srid=None) — converts an rst_h3_gridspec grid struct (Row or dict) to a 1-row EPSG:4326 GeoDataFrame containing the canvas rectangle, with optional pyproj reprojection for non-4326 SRIDs and pixel_size/width/height metadata columns carried through. Adds dissolve_by= keyword arg to cells_as_gdf: when set to a column that is already in extra_cols, returns one dissolved polygon per distinct value (union footprint) instead of one row per cell. Raises ValueError if dissolve_by is not in extra_cols. 9/9 tests pass; black/isort/flake8 clean on changed files. Co-authored-by: Isaac * docs(notebooks): render DEM/polyfill/grid via gbx.viz in isobands demo Wire the three render steps into h3_rasterize_isobands using the viz helpers (grid_as_gdf + cells_as_gdf dissolve_by added in the same change set): - Step 1: plot_file(DEM_PATH) — source DEM. - Step 2: cells_as_gdf(..., dissolve_by="band_level").plot — polyfill, dissolved per band (one footprint polygon per band, efficient vs one-row-per-cell). - Step 3: grid_as_gdf(g) overlaid on the per-band footprints via folium .explore(m=...) — the shared canvas framing the cells (multi-layer on one map). Co-authored-by: Isaac * docs(notebooks): switch isobands demo to San Francisco DEM (N37W123) Replace NYC tile (N40W073, −85..90 m, 1 band) with SF Bay Area tile (N37W123); chosen band params give 6–10 well-populated elevation bands over SF urban+hill terrain. Co-authored-by: Isaac * docs(notebooks): clear stale NYC outputs from SF isobands demo Clean source state after the N37W123 swap (subagent left stale NYC image outputs). User re-runs on the cluster to populate SF renders. Co-authored-by: Isaac * docs(notebooks): SF-specific narrative + distributed-scaling notes for isobands demo - Intro (cell 0): ground terrain in SF facts (Twin Peaks ~280 m, Mt Tamalpais ~784 m, sea level baseline → eight 100 m bands); add SF-specific framing for the telco analogy (hilly coastal city, terrain shadows RF coverage). - Runtime requirement (cell 0): fix "DEM is read from the Volume" → "tile is fetched by the staging cell (public AWS Terrain Tiles, idempotent)". - Cell 5 (DEM parameters): remove "ships with the GeoBrix sample-data Volume"; reword to reflect the staging-cell download flow accurately. - Cell 9 (Step 1 intro): call out explicitly that DEM read + isoband extraction run on the driver (single node); note Spark stages begin in Step 3. - Cell 13 (Step 2 intro): same driver/single-node clarity; expand the production-scale note to name binaryFile + gtiff_gbx reader pattern. - Cell 29 (Summary): annotate step table with (driver)/(Spark); add "Scaling to many tiles" bullet pointing at binaryFile/gtiff_gbx multi-tile distributed-polyfill direction. Co-authored-by: Isaac * feat(viz): plot_raster composite="depth" coverage-depth mode Add `composite` keyword to `plot_raster`, `plot_file`, and the internal `_render` helper. `composite="auto"` (default) preserves existing behaviour (1 band → viridis; 3+ → RGB). `composite="depth"` computes per-pixel band coverage count via the new `_coverage_depth` helper — turns a stack of binary presence masks into a bright 0..N viridis gradient instead of a dark RGB composite; uncovered pixels are masked transparent. TDD: 5 new tests in test_raster.py covering the depth helper (masked array path, plain-ndarray/nodata path, known-geometry verification) and the public API (figure produced for depth mode; auto mode unchanged). All 10 viz tests pass. Co-authored-by: Isaac * docs(notebooks): finer pixel size + coverage-depth stack render (SF isobands) Two render fixes for the H3-isobands notebook: 1. PIXEL_SIZE_DEG — added to params cell (#6) as ~3 px per hex edge at SF latitude (h3.average_hexagon_edge_length / 3 / cos-scaled degrees). Passed to rst_h3_gridspec(pixel_size=PIXEL_SIZE_DEG) in cell #18 so per-band tiles have solid hex footprints rather than scattered specks. 2. composite="depth" — stack render cell (#28) now calls plot_raster(..., composite="depth") to show coverage depth (0..N viridis gradient) instead of an RGB-of-presence-masks composite that reads mostly black. Markdown cell #27 updated to describe the coverage-depth view. Markdown cell #23 notes that the finer pixel size produces solid single-band footprints. No outputs (cluster-only notebook; outputs cleared). Co-authored-by: Isaac * fix(viz): render constant single-band masks (presence) with visible background When a single-band raster holds only one distinct valid value (e.g. an H3 presence mask: 1.0 where covered, NoData=-9999 everywhere else), matplotlib's Normalize ends up with vmin == vmax. That makes the normalizer degenerate: every valid pixel maps to 0.5 in the colormap but the figure background is white, so the image appears blank. Fix: add _single_band_clim(valid) which detects the constant-value case and returns an explicit non-degenerate (vmin, vmax) pair (mapping the constant to the upper end of a [0, const] or [0, 1] interval). The single-band branch of _render now extracts the unmasked values, calls _single_band_clim, and passes vmin/vmax only when needed. ax.set_facecolor("whitesmoke") ensures masked border pixels are visually distinct from the white figure background. Five new tests: four _single_band_clim unit tests (constant-1, constant-0, varying, empty) plus an integration test that constructs a real presence-mask GTiff and asserts a figure is produced. Co-authored-by: Isaac * docs(notebooks): materialize band tiles to session temp table Replace the lazy .orderBy() with a session-scoped CREATE TEMP TABLE so the expensive per-pixel rasterize runs once and steps 8/9 read it back instead of recomputing. This is the Serverless-idiomatic .cache() replacement (.cache and .persist are unavailable there); the table auto-drops at session end. Requires Serverless or DBR 18.1+ (not dedicated/single-user clusters). Also strip trailing newlines from all cells. Co-authored-by: Isaac * docs(notebooks): inspect highest-two band coverage shapes A single band is a binary presence mask (one colour), so the low/dense bands render as a flat filled canvas. Show the highest two thresholds instead -- their footprints cluster on the hilltops, making the coverage shape (and the rasterizer's correctness) actually visible. Reads from the band_tiles temp table, no recompute. Co-authored-by: Isaac * docs(notebooks): inspect mid-coverage bands (clear footprint shape) Highest bands (63/173 cells) are a sparse speck on the 499x505 canvas and the lowest fills it uniformly -- both read as "empty/flat". Auto-pick two mid-coverage bands (8-45% of the densest) so the footprint is a substantial, clearly-shaped region that shrinks with elevation. Clear cell 24's stale output. Co-authored-by: Isaac * fix(viz): draw single-band masks via imshow, not rasterio show() rasterio.plot.show() renders a constant-valued single band (an H3 presence mask, all 1.0) as a blank plot and ignores the explicit vmin/vmax, so every per-band inspection looked empty. Render the single-band branch with ax.imshow + an explicit plotting_extent instead -- it honors the clim and the masked array (NoData -> transparent over the facecolor). Replace the figure-exists check with a real regression test asserting the footprint is actually drawn (non-degenerate clim + coloured pixels in the rasterized buffer); the old check passed while blank. Verified locally across full/mid/sparse coverage and a continuous DEM-like raster. Co-authored-by: Isaac * style(pyrx): clear flake8 dead code + docker-black reformat Remove unused imports (math/numpy in _h3_cell_bbox_udf, math in rst_h3_gridspec) and the dead _mode_val capture (mode is already applied via the bbox UDF), plus an unused numpy import in test_core_cellraster. Reformat test_vector_raster_bridge with in-container black (a prior host-black pass diverged from CI's black). Clears the CI Python-lint gate; no behaviour change. Co-authored-by: Isaac * feat(viz): plot_mask_layers overlay + use it in isobands cell 8 Add plot_mask_layers(layers, colors=, ...): overlay several single-band presence- mask tiles on one axes, each a solid colour with a legend (NoData transparent over a grey facecolor). Tiles must share a grid; draw order is largest-first so nested coverage stays visible. Notebook cell 8 now overlays the two mid-coverage bands on a single plot instead of two separate viridis figures. Regression test asserts two overlaid AxesImages, a 2-entry legend, and both requested colours present in the rasterized buffer. Co-authored-by: Isaac * docs(notebooks): match polyfill markdown to undissolved render + viz summary Cell 16 described dissolve_by as active while the code renders per-cell (kept deliberately: per-cell tooltips read better at this size). Reword to the per-cell render and add a Note pointing at dissolve_by="band_level" for larger sets. Update the summary table's Visualize rows to the actual calls (plot_mask_layers, plot_raster(composite="depth")). Co-authored-by: Isaac * docs: H3 rasterize example page + viz functions + release notes - New docs/docs/notebooks/h3-rasterize.mdx (registered in sidebars.js) documenting the SF Bay Area H3 rasterize -> band-stack example. - viz.mdx: document plot_mask_layers, grid_as_gdf, composite="depth", and the cells_as_gdf dissolve_by option; update the import list. - beta-release-notes: add gbx.viz module bullet + H3 rasterize example bullet. - raster-functions: add explicit {#h3-grid} anchor so release-notes link resolves. - README: retarget the example to the San Francisco DEM, the session temp table, and the new viz helpers. Validated with a full Docusaurus build (no broken links). Co-authored-by: Isaac * docs(raster-functions): link the H3 rasterize notebook from rst_h3_rasterize_agg Add a "Worked example" tip in the rst_h3_rasterize_agg section pointing at the new H3 Rasterize notebook, cross-linking rst_h3_gridspec, rst_frombands_agg, and gbx.viz. Co-authored-by: Isaac * bench: add rst_h3_rasterize_agg to the cluster benchmark (both tiers) New "h3_aggregate" input kind: a fixed 331-cell res-9 H3 set on a hardcoded explicit grid, mirrored byte-for-byte in spec.py (_H3RAGG_*) and BenchDispatch.scala (h3Ragg*) so the light and heavy legs burn the identical cells onto the identical canvas. Python: FnSpec (dggs, spark-path, fingerprint) + _h3_aggregate_df group builder + runner wiring. Scala: DGGS category, h3Aggregate set/inputKind, heavy aggregate case (UDAF -> gbx_rst_fromcontent tile struct), HeavyRunner group branch, BenchDispatchTest count 106->107. Cross-tier masks verified byte-identical (0 px) via the local JAR; Scala bench suite green (20 tests). Co-authored-by: Isaac * bench: heavy rst_h3_rasterize_agg returns a tile struct, do not wrap in fromcontent The heavy UDAF's dataType is tileDataType(BinaryType) -- a tile STRUCT, like rst_rasterize_agg -- so the cluster heavy leg must call gbx_rst_h3_rasterize_agg directly (the consistency collect reads `raster` off the struct). Wrapping it in gbx_rst_fromcontent (a BINARY->struct helper, only needed for the lightweight SQL form) fed a struct where bytes were expected and aborted the distributed agg with "[INTERNAL_ERROR] Couldn't find method eval". Match the rst_rasterize_agg pattern. Co-authored-by: Isaac * fix(pyrx): rst_h3_rasterize_agg null value column burns presence 1.0, not NaN A null in a TYPED (Double) value column arrives in the pandas_udf as np.nan, and `np.nan is not None` is True, so the presence guard burned float(np.nan)=NaN instead of 1.0. Guard with pd.isna. The cluster benchmark caught this as a heavy(1.0)-vs- light(NaN) cross-tier divergence (the value-omitted path was already correct, which is why the JAR-gated parity test passed). Regression test added with an explicit nullable DoubleType value column. Co-authored-by: Isaac * docs(benchmarking): add rst_h3_rasterize_agg spark-path row (heavy 1.5x, exact) Cluster bench (1000 groups, fixed 20 workers): heavy 1.50 ms/tile vs light 2.26 ms/tile (heavy ~1.5x faster), cross-tier parity exact. Footnoted because the H3 rasterizer's workload (331-cell groups -> 39x24 output) differs from the 1024² rows, so the cross-tier ratio + exact parity are the comparable takeaways. Co-authored-by: Isaac * docs(performance): classify rst_h3_rasterize_agg + the custom-grid family Bring the lightweight implementation-techniques page current: add rst_h3_rasterize_agg to the grouped-aggregate UDF table, and a "GridX (pygx) -- custom grid" section in the Arrow scalar tab mirroring the quadbin/BNG families (scalar cell-ops as pandas_udf, array polyfill/kring as plain @udf). Regular scalar UDFs (metadata/accessors, h3_cell_bbox) remain intentionally unlisted. Co-authored-by: Isaac * docs(images): regenerate landscape function-categories PNG (108 fns, H3) The landscape SVG already carried rst_h3_rasterize_agg + the 108 count, but its screenshot PNG was last rendered pre-H3 (107). Re-screenshot from the current SVG so the slide asset matches; the portrait PNG (used on the docs page) was already current. Co-authored-by: Isaac * docs(examples): hero diagrams at the top of each example notebook eo-series 01-04: embed the existing eo-series-0N.png banner after the intro cell. xView + h3-rasterize: new resources/images/example-diagrams.py (reuses the eo-series.py diagram framework via importlib) renders xview-clipping.png and h3-rasterize.png, embedded after each notebook's intro cell and in their READMEs. Includes the executed-notebook + banner edits supplied for the example set. Co-authored-by: Isaac * docs(images): refresh eo-series diagrams to the lightweight tier Update the four eo-series notebook diagrams' chips + captions to match the migrated notebooks: shapefile_ogr→shapefile_gbx, pystac_client→StacClient (01); the deleted download_band/update_assets flow → StacClient.download / StacClient.repair (02); gdal reader→gtiff_gbx, rasterio_lambda→rst_apply (03); gdal writer→gtiff_gbx (04). Tier-agnostic built-ins (h3_tessellateaswkb, st_*) and still-used functions kept. Re-rendered all four PNGs. Also includes the h3 notebook's first-cell edit. Co-authored-by: Isaac --------- Co-authored-by: Michael Johns <user.name>
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps org.locationtech.proj4j:proj4j from 1.3.0 to 1.4.1.
Release notes
Sourced from org.locationtech.proj4j:proj4j's releases.
Changelog
Sourced from org.locationtech.proj4j:proj4j's changelog.
Commits
56c11edpublish to the new central6c7e0ccCHANGELOG.md rotate42d8c26CHANGELOG.md updace6185External GridDefinition read fix (#121)c856914Add sections about how to use GeoAPI in the README file. (#119)5d06d56Update CHANGELOG.mdd399685CHANGELOG.md rotate[2]6562833CHANGELOG.md rotate9a92e99LCC ProjectInverse adjustment, BasicCoordinateTransform.transform cleanup (#117)9016292GeoAPI wrappers for PROJ4J (#115)You can trigger a rebase of this PR by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)