From 796b684575ade2c38e0dbddbda87a2c4fa344842 Mon Sep 17 00:00:00 2001 From: aboydnw Date: Mon, 1 Jun 2026 21:14:40 +0000 Subject: [PATCH 1/3] docs: add Lonboard quickstart notebook Companion notebook for the Lonboard tutorial in PlanetaryComputerDataCatalog. Walks through interactive raster and vector visualization of Planetary Computer data: STAC search, RasterLayer.from_stac, opacity and colormap adjustments, raster + vector layer composition. Co-Authored-By: Claude Opus 4.7 (1M context) --- quickstarts/lonboard.ipynb | 218 +++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 quickstarts/lonboard.ipynb diff --git a/quickstarts/lonboard.ipynb b/quickstarts/lonboard.ipynb new file mode 100644 index 0000000..96909ab --- /dev/null +++ b/quickstarts/lonboard.ipynb @@ -0,0 +1,218 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "51b92224", + "metadata": {}, + "source": [ + "# Visualizing Planetary Computer data with Lonboard\n", + "\n", + "This notebook walks through interactive geospatial visualization with [Lonboard](https://developmentseed.org/lonboard/). Lonboard is a Python library that renders Cloud Optimized GeoTIFFs and vector data on a GPU-accelerated WebGL map directly in Jupyter. Key benefits:\n", + "\n", + "1. **GPU rendering** — handles millions of features without breaking interactivity.\n", + "2. **No tile server** — COG tiles stream straight to the browser; no intermediate service.\n", + "3. **STAC-native** — `RasterLayer.from_stac()` takes signed PC items directly.\n", + "4. **Composable** — stack raster, vector, and overlay layers in one `Map`.\n", + "5. **Live mutation** — change opacity, colormap, or data and the map updates in place.\n", + "\n", + "Each cell below renders a map you can pan and zoom.\n", + "\n", + "The companion [Lonboard tutorial](../overview/lonboard.md) has the full narrative." + ] + }, + { + "cell_type": "markdown", + "id": "f369cf32", + "metadata": {}, + "source": [ + "## Install" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "214ad665", + "metadata": {}, + "outputs": [], + "source": [ + "%pip install --quiet lonboard pystac-client planetary-computer geopandas" + ] + }, + { + "cell_type": "markdown", + "id": "8a7e656a", + "metadata": {}, + "source": [ + "## Open the Planetary Computer STAC catalog\n", + "\n", + "`modifier=planetary_computer.sign_inplace` signs every asset href as the search returns, so Lonboard can fetch tiles directly without a separate signing step.\n", + "\n", + "**Expected result:** working `catalog` client, no output printed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bae9e3c0", + "metadata": {}, + "outputs": [], + "source": [ + "import pystac_client\n", + "import planetary_computer\n", + "\n", + "catalog = pystac_client.Client.open(\n", + " \"https://planetarycomputer.microsoft.com/api/stac/v1\",\n", + " modifier=planetary_computer.sign_inplace,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "e662b1b6", + "metadata": {}, + "source": [ + "## Search NAIP over Portland\n", + "\n", + "**Expected result:** a small handful of items covering the bbox in 2022." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8492bbff", + "metadata": {}, + "outputs": [], + "source": [ + "items = catalog.search(\n", + " collections=[\"naip\"],\n", + " bbox=[-122.7, 45.5, -122.6, 45.6],\n", + " datetime=\"2022-01-01/2023-01-01\",\n", + ").item_collection()\n", + "\n", + "len(items)" + ] + }, + { + "cell_type": "markdown", + "id": "6c4b7ebd", + "metadata": {}, + "source": [ + "## Render the imagery\n", + "\n", + "`RasterLayer.from_stac()` takes the list of items and figures out which COG asset to render. The map below is fully interactive — pan and zoom to load tiles on demand.\n", + "\n", + "**Expected result:** an interactive map of Portland with NAIP imagery." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "379f983c", + "metadata": {}, + "outputs": [], + "source": [ + "from lonboard import Map\n", + "from lonboard.experimental import RasterLayer\n", + "\n", + "layer = RasterLayer.from_stac(items)\n", + "Map(layer)" + ] + }, + { + "cell_type": "markdown", + "id": "eab6648f", + "metadata": {}, + "source": [ + "## Adjust opacity\n", + "\n", + "Mutating the layer in place updates the existing map without re-fetching tiles.\n", + "\n", + "**Expected result:** the same map redraws at 70% opacity." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "69ce4169", + "metadata": {}, + "outputs": [], + "source": [ + "layer.opacity = 0.7" + ] + }, + { + "cell_type": "markdown", + "id": "be01c186", + "metadata": {}, + "source": [ + "## Apply a colormap (single-band rasters)\n", + "\n", + "Useful for NDVI, classification, or any thematic raster. Re-running this cell with a different `colormap_name` (`viridis`, `magma`, `RdBu`, …) compares options without re-fetching tiles.\n", + "\n", + "**Expected result:** a separate map with a styled colormap applied." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "daed39bb", + "metadata": {}, + "outputs": [], + "source": [ + "colormapped = RasterLayer.from_stac(items, colormap_name=\"viridis\", rescale=(-1, 1))\n", + "Map(colormapped)" + ] + }, + { + "cell_type": "markdown", + "id": "cc256790", + "metadata": {}, + "source": [ + "## Combine raster with vector overlays\n", + "\n", + "Layers compose. Draw the STAC item footprints over the imagery:\n", + "\n", + "**Expected result:** the NAIP map with item-boundary lines drawn on top." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9fb235d1", + "metadata": {}, + "outputs": [], + "source": [ + "import geopandas as gpd\n", + "from lonboard import PathLayer\n", + "\n", + "footprints = gpd.GeoDataFrame.from_features(items.to_dict())\n", + "footprint_layer = PathLayer.from_geopandas(\n", + " footprints.boundary.to_frame(\"geometry\")\n", + ")\n", + "\n", + "Map([layer, footprint_layer])" + ] + }, + { + "cell_type": "markdown", + "id": "aae00ff1", + "metadata": {}, + "source": [ + "## You're done\n", + "\n", + "If every cell above rendered a map, the stack is wired up end-to-end: STAC search → signed assets → GPU-rendered raster → vector overlays. Swap in your own bbox, collection, or GeoDataFrame and the same pattern applies.\n", + "\n", + "For pixel-level analysis (window reads, overview traversal), see the [async-geotiff tutorial](../overview/async-geotiff.md). For a standalone web app rather than a notebook, the [deck.gl-raster tutorial](../overview/deckgl-raster.md) builds the same renderer in TypeScript." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From eb944452287854e4958e7f6dfefd011bf7b3c708 Mon Sep 17 00:00:00 2001 From: aboydnw Date: Mon, 1 Jun 2026 23:27:50 +0000 Subject: [PATCH 2/3] feat: pivot lonboard quickstart to vector (building footprints) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The notebook used lonboard.experimental.RasterLayer.from_stac, which does not exist in any released lonboard. Rewrite around lonboard's shipping strength — GPU vector rendering — using Microsoft Building Footprints: read a STAC GeoParquet quadkey partition into a GeoDataFrame, render hundreds of thousands of polygons with PolygonLayer, then color by meanHeight via apply_continuous_cmap. No tile server; geometry streams as Arrow. Co-Authored-By: Claude Opus 4.8 (1M context) --- quickstarts/lonboard.ipynb | 292 +++++++++++++++++++++++++++---------- 1 file changed, 212 insertions(+), 80 deletions(-) diff --git a/quickstarts/lonboard.ipynb b/quickstarts/lonboard.ipynb index 96909ab..2f37d48 100644 --- a/quickstarts/lonboard.ipynb +++ b/quickstarts/lonboard.ipynb @@ -2,27 +2,27 @@ "cells": [ { "cell_type": "markdown", - "id": "51b92224", + "id": "b90cec6c", "metadata": {}, "source": [ "# Visualizing Planetary Computer data with Lonboard\n", "\n", - "This notebook walks through interactive geospatial visualization with [Lonboard](https://developmentseed.org/lonboard/). Lonboard is a Python library that renders Cloud Optimized GeoTIFFs and vector data on a GPU-accelerated WebGL map directly in Jupyter. Key benefits:\n", + "This notebook walks through interactive geospatial visualization with [Lonboard](https://developmentseed.org/lonboard/). Lonboard renders large vector datasets on a GPU-accelerated WebGL map directly in Jupyter. Key benefits:\n", "\n", - "1. **GPU rendering** — handles millions of features without breaking interactivity.\n", - "2. **No tile server** — COG tiles stream straight to the browser; no intermediate service.\n", - "3. **STAC-native** — `RasterLayer.from_stac()` takes signed PC items directly.\n", - "4. **Composable** — stack raster, vector, and overlay layers in one `Map`.\n", - "5. **Live mutation** — change opacity, colormap, or data and the map updates in place.\n", + "1. **GPU rendering** — pan and zoom through *millions* of features without breaking interactivity.\n", + "2. **No tile server** — geometry streams to the browser as [Apache Arrow](https://arrow.apache.org/); there's no intermediate vector-tile service to stand up.\n", + "3. **Cloud-native vector** — read a STAC GeoParquet partition straight off Azure Blob into a `GeoDataFrame`.\n", + "4. **Composable** — stack multiple vector layers in one `Map`.\n", + "5. **Data-driven styling** — color features by an attribute and mutate the layer in place.\n", "\n", - "Each cell below renders a map you can pan and zoom.\n", + "We'll render [Microsoft Building Footprints](https://planetarycomputer.microsoft.com/dataset/ms-buildings) over Portland, Oregon — hundreds of thousands of polygons in a single layer.\n", "\n", "The companion [Lonboard tutorial](../overview/lonboard.md) has the full narrative." ] }, { "cell_type": "markdown", - "id": "f369cf32", + "id": "a75e986e", "metadata": {}, "source": [ "## Install" @@ -30,31 +30,62 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "214ad665", - "metadata": {}, - "outputs": [], + "execution_count": 1, + "id": "2719b6d3", + "metadata": { + "execution": { + "iopub.execute_input": "2026-06-01T23:09:15.849722Z", + "iopub.status.busy": "2026-06-01T23:09:15.849298Z", + "iopub.status.idle": "2026-06-01T23:09:16.915041Z", + "shell.execute_reply": "2026-06-01T23:09:16.913769Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m26.1.2\u001b[0m\r\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython -m pip install --upgrade pip\u001b[0m\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], "source": [ - "%pip install --quiet lonboard pystac-client planetary-computer geopandas" + "%pip install --quiet lonboard pystac-client planetary-computer dask-geopandas adlfs" ] }, { "cell_type": "markdown", - "id": "8a7e656a", + "id": "dd178afe", "metadata": {}, "source": [ "## Open the Planetary Computer STAC catalog\n", "\n", - "`modifier=planetary_computer.sign_inplace` signs every asset href as the search returns, so Lonboard can fetch tiles directly without a separate signing step.\n", + "`modifier=planetary_computer.sign_inplace` signs every asset as the search returns, so the GeoParquet partition can be read directly.\n", "\n", "**Expected result:** working `catalog` client, no output printed." ] }, { "cell_type": "code", - "execution_count": null, - "id": "bae9e3c0", - "metadata": {}, + "execution_count": 2, + "id": "6db7f010", + "metadata": { + "execution": { + "iopub.execute_input": "2026-06-01T23:09:16.917910Z", + "iopub.status.busy": "2026-06-01T23:09:16.917592Z", + "iopub.status.idle": "2026-06-01T23:09:17.905144Z", + "shell.execute_reply": "2026-06-01T23:09:17.903296Z" + } + }, "outputs": [], "source": [ "import pystac_client\n", @@ -68,141 +99,230 @@ }, { "cell_type": "markdown", - "id": "e662b1b6", + "id": "626369d5", "metadata": {}, "source": [ - "## Search NAIP over Portland\n", + "## Find the building-footprints partition for Portland\n", "\n", - "**Expected result:** a small handful of items covering the bbox in 2022." + "The `ms-buildings` collection is partitioned by [quadkey](https://learn.microsoft.com/en-us/bingmaps/articles/bing-maps-tile-system). Compute the zoom-9 quadkey for a Portland coordinate and fetch the STAC item whose partition covers it.\n", + "\n", + "**Expected result:** one matching item and its GeoParquet `data` asset." ] }, { "cell_type": "code", - "execution_count": null, - "id": "8492bbff", - "metadata": {}, - "outputs": [], + "execution_count": 3, + "id": "2e668d74", + "metadata": { + "execution": { + "iopub.execute_input": "2026-06-01T23:09:17.908410Z", + "iopub.status.busy": "2026-06-01T23:09:17.908088Z", + "iopub.status.idle": "2026-06-01T23:09:19.140611Z", + "shell.execute_reply": "2026-06-01T23:09:19.138497Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "('021230223', 'UnitedStates_21230223_2023-04-25')" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "items = catalog.search(\n", - " collections=[\"naip\"],\n", - " bbox=[-122.7, 45.5, -122.6, 45.6],\n", - " datetime=\"2022-01-01/2023-01-01\",\n", - ").item_collection()\n", + "import math\n", "\n", - "len(items)" + "\n", + "def quadkey(lat, lon, zoom):\n", + " n = 2 ** zoom\n", + " x = int((lon + 180.0) / 360.0 * n)\n", + " y = int((1.0 - math.asinh(math.tan(math.radians(lat))) / math.pi) / 2.0 * n)\n", + " digits = []\n", + " for i in range(zoom, 0, -1):\n", + " bit = 1 << (i - 1)\n", + " digits.append(str((1 if x & bit else 0) + (2 if y & bit else 0)))\n", + " return \"\".join(digits)\n", + "\n", + "\n", + "qk = quadkey(45.52, -122.66, 9)\n", + "item = next(catalog.search(\n", + " collections=[\"ms-buildings\"],\n", + " query={\n", + " \"msbuildings:region\": {\"eq\": \"UnitedStates\"},\n", + " \"msbuildings:quadkey\": {\"eq\": int(qk)},\n", + " },\n", + ").items())\n", + "asset = item.assets[\"data\"]\n", + "qk, item.id" ] }, { "cell_type": "markdown", - "id": "6c4b7ebd", + "id": "1bc86af0", "metadata": {}, "source": [ - "## Render the imagery\n", + "## Load the footprints into a GeoDataFrame\n", "\n", - "`RasterLayer.from_stac()` takes the list of items and figures out which COG asset to render. The map below is fully interactive — pan and zoom to load tiles on demand.\n", + "The asset is a Delta/Parquet partition on Azure Blob. `dask_geopandas.read_parquet` reads it with the asset's `table:storage_options` (account + SAS), then `.compute()` materializes a GeoDataFrame. Clip to the Portland metro for a focused view.\n", "\n", - "**Expected result:** an interactive map of Portland with NAIP imagery." + "**Expected result:** a few hundred thousand building polygons." ] }, { "cell_type": "code", - "execution_count": null, - "id": "379f983c", - "metadata": {}, - "outputs": [], + "execution_count": 4, + "id": "8078f767", + "metadata": { + "execution": { + "iopub.execute_input": "2026-06-01T23:09:19.143991Z", + "iopub.status.busy": "2026-06-01T23:09:19.143563Z", + "iopub.status.idle": "2026-06-01T23:09:34.562416Z", + "shell.execute_reply": "2026-06-01T23:09:34.561197Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "324600" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "from lonboard import Map\n", - "from lonboard.experimental import RasterLayer\n", + "import dask_geopandas\n", + "\n", + "gdf = dask_geopandas.read_parquet(\n", + " asset.href,\n", + " storage_options=asset.extra_fields[\"table:storage_options\"],\n", + ").compute()\n", + "gdf = gdf.cx[-122.85:-122.45, 45.42:45.62]\n", "\n", - "layer = RasterLayer.from_stac(items)\n", - "Map(layer)" + "len(gdf)" ] }, { "cell_type": "markdown", - "id": "eab6648f", + "id": "54ac8f51", "metadata": {}, "source": [ - "## Adjust opacity\n", + "## Render the footprints\n", "\n", - "Mutating the layer in place updates the existing map without re-fetching tiles.\n", + "`PolygonLayer.from_geopandas()` uploads the geometry to the GPU as Arrow. The map below is fully interactive — pan and zoom through every building with no tile server in the loop.\n", "\n", - "**Expected result:** the same map redraws at 70% opacity." + "**Expected result:** an interactive map of Portland's building footprints." ] }, { "cell_type": "code", - "execution_count": null, - "id": "69ce4169", - "metadata": {}, + "execution_count": 5, + "id": "fc44a442", + "metadata": { + "execution": { + "iopub.execute_input": "2026-06-01T23:09:34.564879Z", + "iopub.status.busy": "2026-06-01T23:09:34.564469Z", + "iopub.status.idle": "2026-06-01T23:09:35.658328Z", + "shell.execute_reply": "2026-06-01T23:09:35.657485Z" + } + }, "outputs": [], "source": [ - "layer.opacity = 0.7" + "from lonboard import Map, PolygonLayer\n", + "\n", + "layer = PolygonLayer.from_geopandas(\n", + " gdf,\n", + " get_fill_color=[255, 140, 0, 170],\n", + " get_line_color=[90, 40, 0],\n", + " line_width_min_pixels=0.5,\n", + ")\n", + "m = Map(layer, view_state={\"longitude\": -122.66, \"latitude\": 45.52, \"zoom\": 12})\n", + "m" ] }, { "cell_type": "markdown", - "id": "be01c186", + "id": "90f0fe81", "metadata": {}, "source": [ - "## Apply a colormap (single-band rasters)\n", + "## Color by building height\n", "\n", - "Useful for NDVI, classification, or any thematic raster. Re-running this cell with a different `colormap_name` (`viridis`, `magma`, `RdBu`, …) compares options without re-fetching tiles.\n", + "Each footprint carries a `meanHeight`. Map it through a continuous colormap to shade every polygon — data-driven styling across the whole layer, evaluated on the GPU.\n", "\n", - "**Expected result:** a separate map with a styled colormap applied." + "**Expected result:** the same footprints, now colored by height (`plasma`: purple = low, yellow = tall)." ] }, { "cell_type": "code", - "execution_count": null, - "id": "daed39bb", - "metadata": {}, + "execution_count": 6, + "id": "08ea2dc5", + "metadata": { + "execution": { + "iopub.execute_input": "2026-06-01T23:09:35.752527Z", + "iopub.status.busy": "2026-06-01T23:09:35.752195Z", + "iopub.status.idle": "2026-06-01T23:09:35.932090Z", + "shell.execute_reply": "2026-06-01T23:09:35.930838Z" + } + }, "outputs": [], "source": [ - "colormapped = RasterLayer.from_stac(items, colormap_name=\"viridis\", rescale=(-1, 1))\n", - "Map(colormapped)" + "import matplotlib as mpl\n", + "from lonboard.colormap import apply_continuous_cmap\n", + "\n", + "heights = gdf[\"meanHeight\"].clip(0, 30)\n", + "normalized = (heights - heights.min()) / (heights.max() - heights.min())\n", + "\n", + "layer.get_fill_color = apply_continuous_cmap(\n", + " normalized.to_numpy(), mpl.colormaps[\"plasma\"], alpha=0.8\n", + ")\n", + "m" ] }, { "cell_type": "markdown", - "id": "cc256790", + "id": "49ee64a4", "metadata": {}, "source": [ - "## Combine raster with vector overlays\n", + "## Mutate in place\n", "\n", - "Layers compose. Draw the STAC item footprints over the imagery:\n", + "Changing a layer property updates the existing map without re-uploading geometry.\n", "\n", - "**Expected result:** the NAIP map with item-boundary lines drawn on top." + "**Expected result:** the rendered footprints redraw at 50% opacity." ] }, { "cell_type": "code", - "execution_count": null, - "id": "9fb235d1", - "metadata": {}, + "execution_count": 7, + "id": "dc9d1f2a", + "metadata": { + "execution": { + "iopub.execute_input": "2026-06-01T23:09:35.934563Z", + "iopub.status.busy": "2026-06-01T23:09:35.934163Z", + "iopub.status.idle": "2026-06-01T23:09:35.938547Z", + "shell.execute_reply": "2026-06-01T23:09:35.937594Z" + } + }, "outputs": [], "source": [ - "import geopandas as gpd\n", - "from lonboard import PathLayer\n", - "\n", - "footprints = gpd.GeoDataFrame.from_features(items.to_dict())\n", - "footprint_layer = PathLayer.from_geopandas(\n", - " footprints.boundary.to_frame(\"geometry\")\n", - ")\n", - "\n", - "Map([layer, footprint_layer])" + "layer.opacity = 0.5" ] }, { "cell_type": "markdown", - "id": "aae00ff1", + "id": "7c643f03", "metadata": {}, "source": [ "## You're done\n", "\n", - "If every cell above rendered a map, the stack is wired up end-to-end: STAC search → signed assets → GPU-rendered raster → vector overlays. Swap in your own bbox, collection, or GeoDataFrame and the same pattern applies.\n", + "If every cell above rendered a map, the stack is wired up end-to-end: STAC search → cloud GeoParquet → Arrow upload → GPU-rendered vector → data-driven styling — all with no tile server.\n", "\n", - "For pixel-level analysis (window reads, overview traversal), see the [async-geotiff tutorial](../overview/async-geotiff.md). For a standalone web app rather than a notebook, the [deck.gl-raster tutorial](../overview/deckgl-raster.md) builds the same renderer in TypeScript." + "Swap in your own bbox, collection, or `GeoDataFrame` and the same pattern applies. For pixel-level *raster* analysis (window reads, overview traversal), see the [async-geotiff tutorial](../overview/async-geotiff.md). For a standalone web app rather than a notebook, the [deck.gl-raster tutorial](../overview/deckgl-raster.md) builds a raster renderer in TypeScript." ] } ], @@ -211,6 +331,18 @@ "display_name": "Python 3", "language": "python", "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.12" } }, "nbformat": 4, From ac1c4c0e79f6ea5d036b9ef2dfa8423f38d784e9 Mon Sep 17 00:00:00 2001 From: aboydnw Date: Tue, 2 Jun 2026 20:08:48 +0000 Subject: [PATCH 3/3] style: replace em dashes with colons and splits in lonboard quickstart prose Co-Authored-By: Claude Opus 4.8 (1M context) --- quickstarts/lonboard.ipynb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/quickstarts/lonboard.ipynb b/quickstarts/lonboard.ipynb index 2f37d48..58b4cba 100644 --- a/quickstarts/lonboard.ipynb +++ b/quickstarts/lonboard.ipynb @@ -9,13 +9,13 @@ "\n", "This notebook walks through interactive geospatial visualization with [Lonboard](https://developmentseed.org/lonboard/). Lonboard renders large vector datasets on a GPU-accelerated WebGL map directly in Jupyter. Key benefits:\n", "\n", - "1. **GPU rendering** — pan and zoom through *millions* of features without breaking interactivity.\n", - "2. **No tile server** — geometry streams to the browser as [Apache Arrow](https://arrow.apache.org/); there's no intermediate vector-tile service to stand up.\n", - "3. **Cloud-native vector** — read a STAC GeoParquet partition straight off Azure Blob into a `GeoDataFrame`.\n", - "4. **Composable** — stack multiple vector layers in one `Map`.\n", - "5. **Data-driven styling** — color features by an attribute and mutate the layer in place.\n", + "1. **GPU rendering**: pan and zoom through *millions* of features without breaking interactivity.\n", + "2. **No tile server**: geometry streams to the browser as [Apache Arrow](https://arrow.apache.org/); there's no intermediate vector-tile service to stand up.\n", + "3. **Cloud-native vector**: read a STAC GeoParquet partition straight off Azure Blob into a `GeoDataFrame`.\n", + "4. **Composable**: stack multiple vector layers in one `Map`.\n", + "5. **Data-driven styling**: color features by an attribute and mutate the layer in place.\n", "\n", - "We'll render [Microsoft Building Footprints](https://planetarycomputer.microsoft.com/dataset/ms-buildings) over Portland, Oregon — hundreds of thousands of polygons in a single layer.\n", + "We'll render [Microsoft Building Footprints](https://planetarycomputer.microsoft.com/dataset/ms-buildings) over Portland, Oregon: hundreds of thousands of polygons in a single layer.\n", "\n", "The companion [Lonboard tutorial](../overview/lonboard.md) has the full narrative." ] @@ -215,7 +215,7 @@ "source": [ "## Render the footprints\n", "\n", - "`PolygonLayer.from_geopandas()` uploads the geometry to the GPU as Arrow. The map below is fully interactive — pan and zoom through every building with no tile server in the loop.\n", + "`PolygonLayer.from_geopandas()` uploads the geometry to the GPU as Arrow. The map below is fully interactive. Pan and zoom through every building with no tile server in the loop.\n", "\n", "**Expected result:** an interactive map of Portland's building footprints." ] @@ -253,7 +253,7 @@ "source": [ "## Color by building height\n", "\n", - "Each footprint carries a `meanHeight`. Map it through a continuous colormap to shade every polygon — data-driven styling across the whole layer, evaluated on the GPU.\n", + "Each footprint carries a `meanHeight`. Map it through a continuous colormap to shade every polygon: data-driven styling across the whole layer, evaluated on the GPU.\n", "\n", "**Expected result:** the same footprints, now colored by height (`plasma`: purple = low, yellow = tall)." ] @@ -320,7 +320,7 @@ "source": [ "## You're done\n", "\n", - "If every cell above rendered a map, the stack is wired up end-to-end: STAC search → cloud GeoParquet → Arrow upload → GPU-rendered vector → data-driven styling — all with no tile server.\n", + "If every cell above rendered a map, the stack is wired up end-to-end: STAC search → cloud GeoParquet → Arrow upload → GPU-rendered vector → data-driven styling, all with no tile server.\n", "\n", "Swap in your own bbox, collection, or `GeoDataFrame` and the same pattern applies. For pixel-level *raster* analysis (window reads, overview traversal), see the [async-geotiff tutorial](../overview/async-geotiff.md). For a standalone web app rather than a notebook, the [deck.gl-raster tutorial](../overview/deckgl-raster.md) builds a raster renderer in TypeScript." ]