Skip to content

Commit d3d826d

Browse files
authored
Refactor user guide notebooks 10-31 to standard structure (#1003)
* Refactor dasymetric mapping user guide notebook Restructure 14_Dasymetric_Mapping.ipynb to match the standard user guide format. Add coverage for pycnophylactic interpolation and validate_disaggregation. Replace raw ax.imshow with DataArray.plot.imshow, add legends and colorbars, include alert boxes, and close with a four-method comparison panel. * Refactor Mahalanobis Distance user guide notebook Restructure to standard cell layout. Replace ax.imshow with DataArray.plot.imshow, add colorbars, fix colorblind-unsafe green/red pair, add GIS alert boxes, generate preview image. * Refactor hydrology user guide notebook Restructure to standard cell layout. Replace raw imshow with DataArray.plot.imshow, add colorbars and legends, include GIS alert boxes, generate preview image. * Refactor flood analysis user guide notebook Restructure to standard cell layout. Replace raw imshow with DataArray.plot.imshow, add colorbars and legends, include GIS alert boxes for HAND thresholds and CN limitations, generate preview image. * Refactor fire analysis user guide notebook Restructure to standard cell layout. Replace raw imshow with DataArray.plot.imshow, fix red/green colormap, add legends and colorbars, include GIS alert boxes, generate preview image. * Refactor balanced allocation user guide notebook Restructure to standard cell layout. Replace raw imshow with DataArray.plot.imshow, add colorbars and legends, include GIS alert boxes, generate preview image. * Refactor landform classification user guide notebook Restructure to match the standard user guide template: title with module name, preview image, nav links, hillshade overlays using xr.DataArray.plot.imshow, Patch legends, GIS alert boxes for radius units and slope units, and a References section. Data generation switched from hand-rolled Gaussians to generate_terrain for consistency with other notebooks. * Refactor water indices user guide notebook Restructure 20_Water_Indices.ipynb to match the standard user guide format: title/subtitle, preview image, standard imports, single data generation cell, individual analysis sections with legends and GIS alert boxes, and a references section. Replace raw ax.imshow calls with xr.DataArray.plot.imshow, add a more interesting synthetic scene with a lake and river channel, and include a water mask overlay section. * Refactor diffusion user guide notebook Restructure to standard cell layout. Replace raw imshow with DataArray.plot.imshow, add colorbars and legends, include GIS alert boxes, generate preview image. * Refactor morphological operators user guide notebook Restructure the notebook to match the standard user guide format: generate_terrain with hillshade overlays, plot.imshow throughout, GIS alert boxes for edge handling and kernel sizing, circular vs square kernel comparison with legend, and a preview image. * Refactor bilateral filter user guide notebook Restructure to match the standard user guide template: title with subtitle, "What you'll build" preview, consolidated data generation, hillshade overlays, plot.imshow throughout, GIS alert boxes for edge effects and sigma_range selection, cross-section plot with colorblind- safe palette, and references section. * Refactor kriging user guide notebook to match standard structure Restructure the notebook into the established cell sequence: title with subtitle, what-you'll-build overview with preview image and nav links, imports, data section, then individual analysis sections each with markdown intro, code, and optional alerts. Replace all raw ax.imshow calls with xr.DataArray.plot.imshow. Add legends to overlay plots, swap magma for inferno on variance maps, and add GIS alert boxes covering variance interpretation and ordinary vs universal kriging. Generate a preview image saved to images/kriging_preview.png. * Refactor corridor analysis user guide notebook Restructure to standard cell layout with title/subtitle, what-you'll-build, and section pattern. Replace ax.imshow with DataArray.plot.imshow, add source markers and legends, switch to inferno colormap, add GIS alert boxes for threshold units and corridor-vs-pathfinding, add references. * Refactor hydraulic erosion user guide notebook Restructure to standard cell layout. Replace ax.imshow with DataArray.plot.imshow, use coolwarm for difference maps, add colorbar labels, include parameter sensitivity and GPU alert boxes, add references. * Refactor sky view factor user guide notebook Restructure to standard cell layout. Replace bare .plot() with DataArray.plot.imshow, add colorbar labels, include resolution alert box, add references. * Refactor GLCM texture user guide notebook Restructure to standard cell layout. Replace ax.imshow with DataArray.plot.imshow, add colorbars and legends, include gray levels alert box, add references. * Refactor contour lines user guide notebook Restructure to standard cell layout. Replace ax.imshow with DataArray.plot.imshow, add hillshade overlays, remove accessor demo, add references. * Refactor stream analysis user guide notebook Restructure to standard cell layout. Replace ax.imshow with DataArray.plot.imshow, fix cell ordering, add routing model comparison alert box, add references. * Refactor rasterize user guide notebook * Refactor preview user guide notebook * Refactor zonal crosstab user guide notebook * Refactor viewshed user guide notebook * Add execution outputs and preview images for earlier notebooks * Remove plt.show() calls from user guide notebooks plt.show() triggers a UserWarning on non-interactive backends (nbconvert, papermill). Jupyter's inline backend renders figures automatically without it. * Fix matplotlib backend in user guide notebooks Remove matplotlib.use('Agg') which blocks inline rendering in Jupyter. Add %matplotlib inline magic to all notebooks. Fix savefig paths and add pathlib.Path('images').mkdir() guards. Fix broken try/except in notebook 19. Re-execute all notebooks to generate plot outputs. * Fix rotated sigma ellipses in Mahalanobis notebook Ellipse width is rotated by angle, so it needs to match the major eigenvalue. Reversed eigvals order so the major axis aligns with the major eigenvector direction. * Show both original and snapped pour points on watershed plot Red X markers for original hand-placed points, blue dots for snapped positions on channels. Updated preview image to match. * Make pour point markers visible on hydrology watershed plots Increase marker size to s=200, use yellow stars for snapped points and red X's for originals with black edges for contrast against the watershed colors. * Fix pour point coordinates on hydrology plots scatter() was using raw row/col indices while plot.imshow() uses DataArray x/y coordinates. Convert indices to data coords so the markers land on the correct raster cells. * Add neon flow path visualization to hydrology notebook Dilate flow paths to 3px width, use neon colormap on dark background with muted hillshade for high-contrast path visibility. * Re-execute notebooks and fix rasterize scanline off-by-one Add half-pixel offset to scanline edge extraction so integer positions correspond to pixel centers instead of edges. Re-execute notebooks 10, 23-31 to capture updated outputs. * Clear notebook outputs to reduce git bloat * Clean up hydrology notebook plots for legibility Drop terrain colormap drape from basemap (hillshade only), use white backgrounds for flow accumulation plots, raise overlay alpha so data layers read clearly against a single neutral base. * Clean up flood analysis plots for legibility Remove terrain colormap drape, use hillshade-only basemap, raise overlay alpha, and use cleaner sequential colormaps for depth/HAND/ travel time so data reads clearly against the neutral gray base. * Fix contour coordinates to use DataArray coordinate space contours() returned raw array indices, which produced misaligned contour lines when plotted on xarray imshow axes that use the DataArray's coordinate values. Transform output coordinates from array indices to the DataArray's y/x coordinate space via np.interp. Update tests, contour_explorer, and user guide notebook accordingly. * Use generate_terrain in sky view factor notebook, clear all notebook outputs Switch 24_Sky_View_Factor from hand-crafted sinusoidal terrain to generate_terrain with ridged noise and domain warping. Add overlay blend composite panel showing hillshade + SVF together. Clear outputs from all user guide notebooks. * Fix dasymetric limiting variable to keep zero-weight pixels uninhabited Zero-weight pixels (water, parks) were absorbing leftover population during the overflow pass. Set class-0 density cap to 0 by default and restrict overflow distribution to habitable pixels only. Expose class_breaks and density_caps parameters on the public disaggregate API.
1 parent 1f36ee5 commit d3d826d

57 files changed

Lines changed: 5690 additions & 5498 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

examples/contour_explorer.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ def draw_contours():
156156
fill_cmap = "gist_earth"
157157
# Use matplotlib's contourf for fills (our contour lines overlay on top)
158158
cf = ax.contourf(
159-
elev_vals, levels=levels_list, cmap=fill_cmap,
160-
origin="lower", alpha=0.35, extend="both",
159+
xs, ys, elev_vals, levels=levels_list, cmap=fill_cmap,
160+
alpha=0.35, extend="both",
161161
)
162162
fill_artists.extend(cf.collections)
163163

@@ -252,16 +252,24 @@ def update_status():
252252
for spine in ax.spines.values():
253253
spine.set_color("white")
254254

255+
# Map the image extent to the DataArray's coordinate space so that
256+
# contour coordinates (which are in coordinate space) align correctly.
257+
xs = elevation.coords["x"].values
258+
ys = elevation.coords["y"].values
259+
img_extent = [xs[0], xs[-1], ys[0], ys[-1]]
260+
255261
# Hillshade layer
256262
hillshade_img = ax.imshow(
257263
hillshade_vals, cmap="gray", origin="lower",
258264
aspect="equal", interpolation="bilinear", alpha=1.0,
265+
extent=img_extent,
259266
)
260267

261268
# Terrain colour layer
262269
terrain_img = ax.imshow(
263270
elev_vals, cmap="gist_earth", origin="lower",
264271
aspect="equal", interpolation="bilinear", alpha=0.4,
272+
extent=img_extent,
265273
)
266274

267275
# Elevation readout under cursor
@@ -287,12 +295,18 @@ def update_status():
287295

288296
# -- Event handlers ------------------------------------------------------------
289297

298+
def _coord_to_pixel(xdata, ydata):
299+
"""Convert coordinate-space position to nearest pixel indices."""
300+
col = int(round(np.interp(xdata, xs, np.arange(len(xs)))))
301+
row = int(round(np.interp(ydata, ys, np.arange(len(ys)))))
302+
return row, col
303+
304+
290305
def on_click(event):
291306
"""Left-click: add contour at that elevation. Right-click: remove nearest."""
292307
if event.inaxes != ax:
293308
return
294-
col = int(round(event.xdata))
295-
row = int(round(event.ydata))
309+
row, col = _coord_to_pixel(event.xdata, event.ydata)
296310
if not (0 <= row < GRID_H and 0 <= col < GRID_W):
297311
return
298312

@@ -304,7 +318,7 @@ def on_click(event):
304318
snapped = round(elev / 10) * 10
305319
if snapped not in custom_levels:
306320
custom_levels.append(snapped)
307-
marker_positions.append((col, row))
321+
marker_positions.append((event.xdata, event.ydata))
308322
print(f" Added contour at elevation {snapped:.0f} "
309323
f"(clicked {elev:.1f} at pixel {row}, {col})")
310324
_update_markers()
@@ -353,8 +367,7 @@ def on_motion(event):
353367
elev_text.set_text("")
354368
fig.canvas.draw_idle()
355369
return
356-
col = int(round(event.xdata))
357-
row = int(round(event.ydata))
370+
row, col = _coord_to_pixel(event.xdata, event.ydata)
358371
if 0 <= row < GRID_H and 0 <= col < GRID_W:
359372
e = elev_vals[row, col]
360373
elev_text.set_text(f"elev: {e:.1f} m ({row}, {col})")

0 commit comments

Comments
 (0)