Skip to content

Commit e8abfab

Browse files
aboydnwclaude
andcommitted
docs: address Lonboard quickstart review
Mirror tutorial changes to address Kyle Barron's feedback: - Replace the bespoke quadkey() helper with mercantile.tile + mercantile.quadkey; pass the string quadkey to the STAC search (preserves leading zeros). - Swap dask_geopandas for the canonical deltalake + geopandas pattern used by the existing ms-buildings example notebook, building storage_options with sas_token from the asset's credential field. - Update install list to match: drop dask-geopandas, add deltalake, geopandas, mercantile; keep adlfs for Azure access. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ac1c4c0 commit e8abfab

1 file changed

Lines changed: 12 additions & 100 deletions

File tree

quickstarts/lonboard.ipynb

Lines changed: 12 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
},
3131
{
3232
"cell_type": "code",
33-
"execution_count": 1,
33+
"execution_count": null,
3434
"id": "2719b6d3",
3535
"metadata": {
3636
"execution": {
@@ -40,27 +40,8 @@
4040
"shell.execute_reply": "2026-06-01T23:09:16.913769Z"
4141
}
4242
},
43-
"outputs": [
44-
{
45-
"name": "stdout",
46-
"output_type": "stream",
47-
"text": [
48-
"\r\n",
49-
"\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",
50-
"\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"
51-
]
52-
},
53-
{
54-
"name": "stdout",
55-
"output_type": "stream",
56-
"text": [
57-
"Note: you may need to restart the kernel to use updated packages.\n"
58-
]
59-
}
60-
],
61-
"source": [
62-
"%pip install --quiet lonboard pystac-client planetary-computer dask-geopandas adlfs"
63-
]
43+
"outputs": [],
44+
"source": "%pip install --quiet lonboard pystac-client planetary-computer geopandas deltalake adlfs mercantile"
6445
},
6546
{
6647
"cell_type": "markdown",
@@ -101,17 +82,11 @@
10182
"cell_type": "markdown",
10283
"id": "626369d5",
10384
"metadata": {},
104-
"source": [
105-
"## Find the building-footprints partition for Portland\n",
106-
"\n",
107-
"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",
108-
"\n",
109-
"**Expected result:** one matching item and its GeoParquet `data` asset."
110-
]
85+
"source": "## Find the building-footprints partition for Portland\n\nThe `ms-buildings` collection is partitioned by [quadkey](https://learn.microsoft.com/en-us/bingmaps/articles/bing-maps-tile-system). Use `mercantile` to convert a Portland coordinate to a zoom-9 quadkey, then fetch the STAC item whose partition covers it.\n\n**Expected result:** one matching item and its Delta Table `data` asset."
11186
},
11287
{
11388
"cell_type": "code",
114-
"execution_count": 3,
89+
"execution_count": null,
11590
"id": "2e668d74",
11691
"metadata": {
11792
"execution": {
@@ -121,60 +96,18 @@
12196
"shell.execute_reply": "2026-06-01T23:09:19.138497Z"
12297
}
12398
},
124-
"outputs": [
125-
{
126-
"data": {
127-
"text/plain": [
128-
"('021230223', 'UnitedStates_21230223_2023-04-25')"
129-
]
130-
},
131-
"execution_count": 3,
132-
"metadata": {},
133-
"output_type": "execute_result"
134-
}
135-
],
136-
"source": [
137-
"import math\n",
138-
"\n",
139-
"\n",
140-
"def quadkey(lat, lon, zoom):\n",
141-
" n = 2 ** zoom\n",
142-
" x = int((lon + 180.0) / 360.0 * n)\n",
143-
" y = int((1.0 - math.asinh(math.tan(math.radians(lat))) / math.pi) / 2.0 * n)\n",
144-
" digits = []\n",
145-
" for i in range(zoom, 0, -1):\n",
146-
" bit = 1 << (i - 1)\n",
147-
" digits.append(str((1 if x & bit else 0) + (2 if y & bit else 0)))\n",
148-
" return \"\".join(digits)\n",
149-
"\n",
150-
"\n",
151-
"qk = quadkey(45.52, -122.66, 9)\n",
152-
"item = next(catalog.search(\n",
153-
" collections=[\"ms-buildings\"],\n",
154-
" query={\n",
155-
" \"msbuildings:region\": {\"eq\": \"UnitedStates\"},\n",
156-
" \"msbuildings:quadkey\": {\"eq\": int(qk)},\n",
157-
" },\n",
158-
").items())\n",
159-
"asset = item.assets[\"data\"]\n",
160-
"qk, item.id"
161-
]
99+
"outputs": [],
100+
"source": "import mercantile\n\ntile = mercantile.tile(-122.66, 45.52, 9)\nquadkey = mercantile.quadkey(*tile)\n\nitem = next(catalog.search(\n collections=[\"ms-buildings\"],\n query={\n \"msbuildings:region\": {\"eq\": \"UnitedStates\"},\n \"msbuildings:quadkey\": {\"eq\": quadkey},\n },\n).items())\nasset = item.assets[\"data\"]\nquadkey, item.id"
162101
},
163102
{
164103
"cell_type": "markdown",
165104
"id": "1bc86af0",
166105
"metadata": {},
167-
"source": [
168-
"## Load the footprints into a GeoDataFrame\n",
169-
"\n",
170-
"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",
171-
"\n",
172-
"**Expected result:** a few hundred thousand building polygons."
173-
]
106+
"source": "## Load the footprints into a GeoDataFrame\n\nThe asset is a Delta Table partition on Azure Blob. Open it with `deltalake`, enumerate the parquet files in the partition, then read each one with `geopandas`. Clip to the Portland metro for a focused view.\n\n**Expected result:** a few hundred thousand building polygons."
174107
},
175108
{
176109
"cell_type": "code",
177-
"execution_count": 4,
110+
"execution_count": null,
178111
"id": "8078f767",
179112
"metadata": {
180113
"execution": {
@@ -184,29 +117,8 @@
184117
"shell.execute_reply": "2026-06-01T23:09:34.561197Z"
185118
}
186119
},
187-
"outputs": [
188-
{
189-
"data": {
190-
"text/plain": [
191-
"324600"
192-
]
193-
},
194-
"execution_count": 4,
195-
"metadata": {},
196-
"output_type": "execute_result"
197-
}
198-
],
199-
"source": [
200-
"import dask_geopandas\n",
201-
"\n",
202-
"gdf = dask_geopandas.read_parquet(\n",
203-
" asset.href,\n",
204-
" storage_options=asset.extra_fields[\"table:storage_options\"],\n",
205-
").compute()\n",
206-
"gdf = gdf.cx[-122.85:-122.45, 45.42:45.62]\n",
207-
"\n",
208-
"len(gdf)"
209-
]
120+
"outputs": [],
121+
"source": "import geopandas as gpd\nimport pandas as pd\nfrom deltalake import DeltaTable\n\nstorage_options = {\n \"account_name\": asset.extra_fields[\"table:storage_options\"][\"account_name\"],\n \"sas_token\": asset.extra_fields[\"table:storage_options\"][\"credential\"],\n}\ntable = DeltaTable(asset.href, storage_options=storage_options)\ngdf = pd.concat([\n gpd.read_parquet(uri, storage_options=storage_options)\n for uri in table.file_uris()\n])\ngdf = gdf.cx[-122.85:-122.45, 45.42:45.62]\n\nlen(gdf)"
210122
},
211123
{
212124
"cell_type": "markdown",
@@ -347,4 +259,4 @@
347259
},
348260
"nbformat": 4,
349261
"nbformat_minor": 5
350-
}
262+
}

0 commit comments

Comments
 (0)