Skip to content

Commit e0a71df

Browse files
committed
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.
1 parent e7a9d29 commit e0a71df

File tree

1 file changed

+74
-81
lines changed

1 file changed

+74
-81
lines changed

examples/user_guide/12_Flood_Analysis.ipynb

Lines changed: 74 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@
4444
"id": "imports",
4545
"metadata": {
4646
"execution": {
47-
"iopub.execute_input": "2026-03-12T15:58:16.201132Z",
48-
"iopub.status.busy": "2026-03-12T15:58:16.201023Z",
49-
"iopub.status.idle": "2026-03-12T15:58:17.345528Z",
50-
"shell.execute_reply": "2026-03-12T15:58:17.344603Z"
47+
"iopub.execute_input": "2026-03-13T02:48:12.809031Z",
48+
"iopub.status.busy": "2026-03-13T02:48:12.808873Z",
49+
"iopub.status.idle": "2026-03-13T02:48:15.149242Z",
50+
"shell.execute_reply": "2026-03-13T02:48:15.148679Z"
5151
}
5252
},
5353
"outputs": [],
@@ -80,10 +80,10 @@
8080
"id": "load-dem",
8181
"metadata": {
8282
"execution": {
83-
"iopub.execute_input": "2026-03-12T15:58:17.347258Z",
84-
"iopub.status.busy": "2026-03-12T15:58:17.346967Z",
85-
"iopub.status.idle": "2026-03-12T15:58:18.575181Z",
86-
"shell.execute_reply": "2026-03-12T15:58:18.574616Z"
83+
"iopub.execute_input": "2026-03-13T02:48:15.150597Z",
84+
"iopub.status.busy": "2026-03-13T02:48:15.150328Z",
85+
"iopub.status.idle": "2026-03-13T02:48:17.828701Z",
86+
"shell.execute_reply": "2026-03-13T02:48:17.828047Z"
8787
}
8888
},
8989
"outputs": [],
@@ -128,10 +128,10 @@
128128
"id": "hydro-setup",
129129
"metadata": {
130130
"execution": {
131-
"iopub.execute_input": "2026-03-12T15:58:18.576434Z",
132-
"iopub.status.busy": "2026-03-12T15:58:18.576174Z",
133-
"iopub.status.idle": "2026-03-12T15:58:19.593667Z",
134-
"shell.execute_reply": "2026-03-12T15:58:19.592846Z"
131+
"iopub.execute_input": "2026-03-13T02:48:17.829970Z",
132+
"iopub.status.busy": "2026-03-13T02:48:17.829696Z",
133+
"iopub.status.idle": "2026-03-13T02:48:18.999397Z",
134+
"shell.execute_reply": "2026-03-13T02:48:18.998831Z"
135135
}
136136
},
137137
"outputs": [],
@@ -159,18 +159,18 @@
159159
"id": "basemap",
160160
"metadata": {
161161
"execution": {
162-
"iopub.execute_input": "2026-03-12T15:58:19.595270Z",
163-
"iopub.status.busy": "2026-03-12T15:58:19.595161Z",
164-
"iopub.status.idle": "2026-03-12T15:58:20.065838Z",
165-
"shell.execute_reply": "2026-03-12T15:58:20.065162Z"
162+
"iopub.execute_input": "2026-03-13T02:48:19.000845Z",
163+
"iopub.status.busy": "2026-03-13T02:48:19.000727Z",
164+
"iopub.status.idle": "2026-03-13T02:48:19.338846Z",
165+
"shell.execute_reply": "2026-03-13T02:48:19.338124Z"
166166
}
167167
},
168168
"outputs": [],
169169
"source": [
170170
"# Build a hillshade basemap we'll reuse throughout\n",
171171
"hillshade = xrspatial.hillshade(dem)\n",
172172
"\n",
173-
"stream_cmap = LinearSegmentedColormap.from_list('water', ['lightblue', 'darkblue'])\n",
173+
"stream_cmap = LinearSegmentedColormap.from_list('water', ['#6baed6', '#08306b'])\n",
174174
"\n",
175175
"# Extract the stream network for context\n",
176176
"threshold = 200\n",
@@ -182,10 +182,9 @@
182182
"\n",
183183
"fig, ax = plt.subplots(figsize=(10, 7.5))\n",
184184
"hillshade.plot.imshow(ax=ax, cmap='gray', add_colorbar=False)\n",
185-
"dem.plot.imshow(ax=ax, cmap='terrain', alpha=0.5, add_colorbar=False)\n",
186-
"streams.plot.imshow(ax=ax, cmap=stream_cmap, alpha=220/255, add_colorbar=False,\n",
185+
"streams.plot.imshow(ax=ax, cmap=stream_cmap, alpha=0.9, add_colorbar=False,\n",
187186
" norm=LogNorm(vmin=stream_vmin))\n",
188-
"ax.legend(handles=[Patch(facecolor='steelblue', alpha=0.86, label='Stream network')],\n",
187+
"ax.legend(handles=[Patch(facecolor='#2171b5', label='Stream network')],\n",
189188
" loc='lower right', fontsize=11, framealpha=0.9)\n",
190189
"ax.set_axis_off()\n",
191190
"plt.tight_layout()"
@@ -217,10 +216,10 @@
217216
"id": "hand",
218217
"metadata": {
219218
"execution": {
220-
"iopub.execute_input": "2026-03-12T15:58:20.068367Z",
221-
"iopub.status.busy": "2026-03-12T15:58:20.068262Z",
222-
"iopub.status.idle": "2026-03-12T15:58:20.603342Z",
223-
"shell.execute_reply": "2026-03-12T15:58:20.602558Z"
219+
"iopub.execute_input": "2026-03-13T02:48:19.340736Z",
220+
"iopub.status.busy": "2026-03-13T02:48:19.340620Z",
221+
"iopub.status.idle": "2026-03-13T02:48:19.901710Z",
222+
"shell.execute_reply": "2026-03-13T02:48:19.901260Z"
224223
}
225224
},
226225
"outputs": [],
@@ -230,11 +229,11 @@
230229
"print(f\"HAND range: {np.nanmin(hand_raster.values):.1f} to \"\n",
231230
" f\"{np.nanmax(hand_raster.values):.1f} m\")\n",
232231
"\n",
233-
"hand_cmap = LinearSegmentedColormap.from_list('hand', ['darkblue', 'cyan', 'yellow', 'red'])\n",
232+
"hand_cmap = LinearSegmentedColormap.from_list('hand', ['#08306b', '#2171b5', '#fee08b', '#d73027'])\n",
234233
"\n",
235234
"fig, ax = plt.subplots(figsize=(10, 7.5))\n",
236235
"hillshade.plot.imshow(ax=ax, cmap='gray', add_colorbar=False)\n",
237-
"hand_raster.plot.imshow(ax=ax, cmap=hand_cmap, alpha=160/255, add_colorbar=True,\n",
236+
"hand_raster.plot.imshow(ax=ax, cmap=hand_cmap, alpha=0.75, add_colorbar=True,\n",
238237
" cbar_kwargs={'label': 'HAND (m)', 'shrink': 0.7})\n",
239238
"ax.set_axis_off()\n",
240239
"plt.tight_layout()"
@@ -268,10 +267,10 @@
268267
"id": "inundation",
269268
"metadata": {
270269
"execution": {
271-
"iopub.execute_input": "2026-03-12T15:58:20.605224Z",
272-
"iopub.status.busy": "2026-03-12T15:58:20.605116Z",
273-
"iopub.status.idle": "2026-03-12T15:58:20.614417Z",
274-
"shell.execute_reply": "2026-03-12T15:58:20.613315Z"
270+
"iopub.execute_input": "2026-03-13T02:48:19.904535Z",
271+
"iopub.status.busy": "2026-03-13T02:48:19.904425Z",
272+
"iopub.status.idle": "2026-03-13T02:48:19.912541Z",
273+
"shell.execute_reply": "2026-03-13T02:48:19.912025Z"
275274
}
276275
},
277276
"outputs": [],
@@ -289,10 +288,10 @@
289288
"id": "inundation-viz",
290289
"metadata": {
291290
"execution": {
292-
"iopub.execute_input": "2026-03-12T15:58:20.615814Z",
293-
"iopub.status.busy": "2026-03-12T15:58:20.615698Z",
294-
"iopub.status.idle": "2026-03-12T15:58:21.035448Z",
295-
"shell.execute_reply": "2026-03-12T15:58:21.034852Z"
291+
"iopub.execute_input": "2026-03-13T02:48:19.913599Z",
292+
"iopub.status.busy": "2026-03-13T02:48:19.913498Z",
293+
"iopub.status.idle": "2026-03-13T02:48:20.201718Z",
294+
"shell.execute_reply": "2026-03-13T02:48:20.200986Z"
296295
}
297296
},
298297
"outputs": [],
@@ -306,10 +305,9 @@
306305
"\n",
307306
"fig, ax = plt.subplots(figsize=(10, 7.5))\n",
308307
"hillshade.plot.imshow(ax=ax, cmap='gray', add_colorbar=False)\n",
309-
"dem.plot.imshow(ax=ax, cmap='terrain', alpha=0.5, add_colorbar=False)\n",
310308
"flood_viz.plot.imshow(ax=ax, cmap=ListedColormap(['steelblue']),\n",
311-
" alpha=200/255, add_colorbar=False)\n",
312-
"ax.legend(handles=[Patch(facecolor='steelblue', alpha=0.78, label='Flooded (10 m)')],\n",
309+
" alpha=0.8, add_colorbar=False)\n",
310+
"ax.legend(handles=[Patch(facecolor='steelblue', alpha=0.8, label='Flooded (10 m)')],\n",
313311
" loc='lower right', fontsize=11, framealpha=0.9)\n",
314312
"ax.set_axis_off()\n",
315313
"plt.tight_layout()"
@@ -343,10 +341,10 @@
343341
"id": "depth",
344342
"metadata": {
345343
"execution": {
346-
"iopub.execute_input": "2026-03-12T15:58:21.036983Z",
347-
"iopub.status.busy": "2026-03-12T15:58:21.036879Z",
348-
"iopub.status.idle": "2026-03-12T15:58:21.425147Z",
349-
"shell.execute_reply": "2026-03-12T15:58:21.424340Z"
344+
"iopub.execute_input": "2026-03-13T02:48:20.203145Z",
345+
"iopub.status.busy": "2026-03-13T02:48:20.203019Z",
346+
"iopub.status.idle": "2026-03-13T02:48:20.469517Z",
347+
"shell.execute_reply": "2026-03-13T02:48:20.468837Z"
350348
}
351349
},
352350
"outputs": [],
@@ -360,12 +358,11 @@
360358
"print(f\" median: {np.median(flooded_vals):.2f} m\")\n",
361359
"print(f\" max: {flooded_vals.max():.2f} m\")\n",
362360
"\n",
363-
"heat_cmap = LinearSegmentedColormap.from_list('heat', ['lightyellow', 'orange', 'darkred'])\n",
361+
"depth_cmap = LinearSegmentedColormap.from_list('depth', ['#ffffcc', '#fd8d3c', '#800026'])\n",
364362
"\n",
365363
"fig, ax = plt.subplots(figsize=(10, 7.5))\n",
366364
"hillshade.plot.imshow(ax=ax, cmap='gray', add_colorbar=False)\n",
367-
"dem.plot.imshow(ax=ax, cmap='terrain', alpha=0.5, add_colorbar=False)\n",
368-
"depth.plot.imshow(ax=ax, cmap=heat_cmap, alpha=200/255, add_colorbar=True,\n",
365+
"depth.plot.imshow(ax=ax, cmap=depth_cmap, alpha=0.85, add_colorbar=True,\n",
369366
" cbar_kwargs={'label': 'Flood depth (m)', 'shrink': 0.7})\n",
370367
"ax.set_axis_off()\n",
371368
"plt.tight_layout()"
@@ -389,10 +386,10 @@
389386
"id": "cn-scalar",
390387
"metadata": {
391388
"execution": {
392-
"iopub.execute_input": "2026-03-12T15:58:21.428035Z",
393-
"iopub.status.busy": "2026-03-12T15:58:21.427929Z",
394-
"iopub.status.idle": "2026-03-12T15:58:21.436698Z",
395-
"shell.execute_reply": "2026-03-12T15:58:21.435921Z"
389+
"iopub.execute_input": "2026-03-13T02:48:20.470974Z",
390+
"iopub.status.busy": "2026-03-13T02:48:20.470859Z",
391+
"iopub.status.idle": "2026-03-13T02:48:20.478920Z",
392+
"shell.execute_reply": "2026-03-13T02:48:20.478270Z"
396393
}
397394
},
398395
"outputs": [],
@@ -424,10 +421,10 @@
424421
"id": "cn-spatial",
425422
"metadata": {
426423
"execution": {
427-
"iopub.execute_input": "2026-03-12T15:58:21.437987Z",
428-
"iopub.status.busy": "2026-03-12T15:58:21.437879Z",
429-
"iopub.status.idle": "2026-03-12T15:58:21.720498Z",
430-
"shell.execute_reply": "2026-03-12T15:58:21.720008Z"
424+
"iopub.execute_input": "2026-03-13T02:48:20.480047Z",
425+
"iopub.status.busy": "2026-03-13T02:48:20.479949Z",
426+
"iopub.status.idle": "2026-03-13T02:48:20.764827Z",
427+
"shell.execute_reply": "2026-03-13T02:48:20.764276Z"
431428
}
432429
},
433430
"outputs": [],
@@ -444,11 +441,11 @@
444441
"print(f\" valley (CN=85): {runoff.values[cn_raster.values == 85].mean():.1f} mm\")\n",
445442
"print(f\" hills (CN=55): {runoff.values[cn_raster.values == 55].mean():.1f} mm\")\n",
446443
"\n",
447-
"heat_cmap = LinearSegmentedColormap.from_list('heat', ['lightyellow', 'orange', 'darkred'])\n",
444+
"runoff_cmap = LinearSegmentedColormap.from_list('runoff', ['#ffffcc', '#fd8d3c', '#800026'])\n",
448445
"\n",
449446
"fig, ax = plt.subplots(figsize=(10, 7.5))\n",
450447
"hillshade.plot.imshow(ax=ax, cmap='gray', add_colorbar=False)\n",
451-
"runoff.plot.imshow(ax=ax, cmap=heat_cmap, alpha=200/255, add_colorbar=True,\n",
448+
"runoff.plot.imshow(ax=ax, cmap=runoff_cmap, alpha=0.8, add_colorbar=True,\n",
452449
" cbar_kwargs={'label': 'Runoff (mm)', 'shrink': 0.7})\n",
453450
"ax.set_axis_off()\n",
454451
"plt.tight_layout()"
@@ -482,10 +479,10 @@
482479
"id": "tt-inputs",
483480
"metadata": {
484481
"execution": {
485-
"iopub.execute_input": "2026-03-12T15:58:21.721815Z",
486-
"iopub.status.busy": "2026-03-12T15:58:21.721702Z",
487-
"iopub.status.idle": "2026-03-12T15:58:22.111770Z",
488-
"shell.execute_reply": "2026-03-12T15:58:22.110884Z"
482+
"iopub.execute_input": "2026-03-13T02:48:20.766341Z",
483+
"iopub.status.busy": "2026-03-13T02:48:20.766235Z",
484+
"iopub.status.idle": "2026-03-13T02:48:21.170917Z",
485+
"shell.execute_reply": "2026-03-13T02:48:21.170083Z"
489486
}
490487
},
491488
"outputs": [],
@@ -505,10 +502,10 @@
505502
"id": "tt-compute",
506503
"metadata": {
507504
"execution": {
508-
"iopub.execute_input": "2026-03-12T15:58:22.113145Z",
509-
"iopub.status.busy": "2026-03-12T15:58:22.113043Z",
510-
"iopub.status.idle": "2026-03-12T15:58:22.419928Z",
511-
"shell.execute_reply": "2026-03-12T15:58:22.419212Z"
505+
"iopub.execute_input": "2026-03-13T02:48:21.172210Z",
506+
"iopub.status.busy": "2026-03-13T02:48:21.172107Z",
507+
"iopub.status.idle": "2026-03-13T02:48:21.478814Z",
508+
"shell.execute_reply": "2026-03-13T02:48:21.478274Z"
512509
}
513510
},
514511
"outputs": [],
@@ -521,12 +518,12 @@
521518
"print(f\"Travel time range: {tt_vals.min():.1f} to {tc:.1f}\")\n",
522519
"print(f\"Time of concentration (max travel time): {tc:.1f}\")\n",
523520
"\n",
524-
"tt_cmap = LinearSegmentedColormap.from_list('tt', ['darkblue', 'cyan', 'yellow', 'red'])\n",
521+
"tt_cmap = LinearSegmentedColormap.from_list('tt', ['#08306b', '#2171b5', '#fee08b', '#d73027'])\n",
525522
"vmin, vmax = np.nanpercentile(tt_vals[np.isfinite(tt_vals)], [2, 98])\n",
526523
"\n",
527524
"fig, ax = plt.subplots(figsize=(10, 7.5))\n",
528525
"hillshade.plot.imshow(ax=ax, cmap='gray', add_colorbar=False)\n",
529-
"tt.plot.imshow(ax=ax, cmap=tt_cmap, alpha=160/255, vmin=vmin, vmax=vmax,\n",
526+
"tt.plot.imshow(ax=ax, cmap=tt_cmap, alpha=0.75, vmin=vmin, vmax=vmax,\n",
530527
" add_colorbar=True,\n",
531528
" cbar_kwargs={'label': 'Travel time', 'shrink': 0.7})\n",
532529
"ax.set_axis_off()\n",
@@ -539,10 +536,10 @@
539536
"id": "tt-compare",
540537
"metadata": {
541538
"execution": {
542-
"iopub.execute_input": "2026-03-12T15:58:22.422157Z",
543-
"iopub.status.busy": "2026-03-12T15:58:22.422049Z",
544-
"iopub.status.idle": "2026-03-12T15:58:22.432903Z",
545-
"shell.execute_reply": "2026-03-12T15:58:22.432326Z"
539+
"iopub.execute_input": "2026-03-13T02:48:21.481411Z",
540+
"iopub.status.busy": "2026-03-13T02:48:21.481303Z",
541+
"iopub.status.idle": "2026-03-13T02:48:21.491759Z",
542+
"shell.execute_reply": "2026-03-13T02:48:21.491111Z"
546543
}
547544
},
548545
"outputs": [],
@@ -585,41 +582,37 @@
585582
"id": "final-map",
586583
"metadata": {
587584
"execution": {
588-
"iopub.execute_input": "2026-03-12T15:58:22.434071Z",
589-
"iopub.status.busy": "2026-03-12T15:58:22.433972Z",
590-
"iopub.status.idle": "2026-03-12T15:58:23.394311Z",
591-
"shell.execute_reply": "2026-03-12T15:58:23.393510Z"
585+
"iopub.execute_input": "2026-03-13T02:48:21.493197Z",
586+
"iopub.status.busy": "2026-03-13T02:48:21.493089Z",
587+
"iopub.status.idle": "2026-03-13T02:48:22.232191Z",
588+
"shell.execute_reply": "2026-03-13T02:48:22.231319Z"
592589
}
593590
},
594591
"outputs": [],
595592
"source": [
596593
"# Final composite: 10 m flood scenario\n",
597-
"import os as _os\n",
598-
"\n",
599594
"depth_10m = flood_depth(hand_raster, water_level=10)\n",
600595
"\n",
601596
"n_flooded = int(np.sum(~np.isnan(depth_10m.values)))\n",
602597
"pct_flooded = 100 * n_flooded / (H * W)\n",
603598
"print(f\"10 m flood scenario: {n_flooded} cells flooded ({pct_flooded:.1f}% of grid)\")\n",
604599
"print(f\"Median depth in flooded area: {np.nanmedian(depth_10m.values):.1f} m\")\n",
605600
"\n",
606-
"heat_cmap = LinearSegmentedColormap.from_list('heat', ['lightyellow', 'orange', 'darkred'])\n",
601+
"depth_cmap = LinearSegmentedColormap.from_list('depth', ['#ffffcc', '#fd8d3c', '#800026'])\n",
607602
"\n",
608603
"fig, ax = plt.subplots(figsize=(10, 7.5))\n",
609604
"hillshade.plot.imshow(ax=ax, cmap='gray', add_colorbar=False)\n",
610-
"dem.plot.imshow(ax=ax, cmap='terrain', alpha=0.5, add_colorbar=False)\n",
611-
"depth_10m.plot.imshow(ax=ax, cmap=heat_cmap, alpha=200/255, add_colorbar=True,\n",
605+
"depth_10m.plot.imshow(ax=ax, cmap=depth_cmap, alpha=0.85, add_colorbar=True,\n",
612606
" cbar_kwargs={'label': 'Flood depth (m)', 'shrink': 0.7})\n",
613-
"streams.plot.imshow(ax=ax, cmap='Blues', alpha=100/255, add_colorbar=False,\n",
607+
"streams.plot.imshow(ax=ax, cmap='Blues', alpha=0.5, add_colorbar=False,\n",
614608
" norm=LogNorm(vmin=stream_vmin))\n",
615-
"ax.legend(handles=[Patch(facecolor='darkorange', alpha=0.78, label='Flood depth'),\n",
616-
" Patch(facecolor='steelblue', alpha=0.39, label='Stream network')],\n",
609+
"ax.legend(handles=[Patch(facecolor='#fd8d3c', label='Flood depth'),\n",
610+
" Patch(facecolor='steelblue', alpha=0.5, label='Stream network')],\n",
617611
" loc='lower right', fontsize=11, framealpha=0.9)\n",
618612
"ax.set_axis_off()\n",
619613
"plt.tight_layout()\n",
620614
"\n",
621615
"# Save preview image\n",
622-
"_os.makedirs('images', exist_ok=True)\n",
623616
"import pathlib\n",
624617
"pathlib.Path('images').mkdir(exist_ok=True)\n",
625618
"fig.savefig('images/flood_analysis_preview.png', bbox_inches='tight', dpi=120)"

0 commit comments

Comments
 (0)