Skip to content

Commit

Permalink
Add contextual layers for SIMD and population density.
Browse files Browse the repository at this point in the history
  • Loading branch information
dabreegster committed Feb 14, 2025
1 parent 8f49d4f commit bb7a388
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 1 deletion.
16 changes: 16 additions & 0 deletions data_prep/scotland/get_reference_layers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ function bus_routes {
tippecanoe tmp/bus_routes_v2.geojson -zg -l bus_routes -o $OUT/bus_routes.pmtiles
}

function population {
# From https://www.data.gov.uk/dataset/1102bf85-ed49-440a-b211-da87e8d752eb/scottish-index-of-multiple-deprivation-simd-2020
download_to_subdir tmp https://maps.gov.scot/ATOM/shapefiles/SG_SIMD_2020.zip
cd tmp
unzip SG_SIMD_2020.zip
ogr2ogr population.geojson \
-t_srs EPSG:4326 \
SG_SIMD_2020.shp \
-nlt PROMOTE_TO_MULTI \
-sql 'SELECT DataZone as id, Rankv2 as imd_rank, Percentv2 as imd_percentile, SAPE2017 as population, OGR_GEOM_AREA as area FROM SG_SIMD_2020'
rm -f SG_SIMD_2020* SIMD2020v2*xlsx
cd ..
tippecanoe tmp/population.geojson -zg --generate-ids -l population -o $OUT/population.pmtiles
}

function get_scotland_osm {
# Download Scotland OSM data
if [ ! -f tmp/scotland-latest.osm.pbf ]; then
Expand All @@ -88,6 +103,7 @@ download_to_subdir() {
#cbd
#railway_stations
#bus_routes
#population

echo "For maintainer only:"
echo " mv $OUT/* ~/cloudflare_sync/cnt_layers/"
Expand Down
2 changes: 1 addition & 1 deletion web/src/AutoBoundariesMode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
type LayerClickInfo,
} from "svelte-maplibre";
import { downloadGeneratedFile } from "svelte-utils";
import { isLine, isPolygon, Popup } from "svelte-utils/map";
import { isLine, isPolygon } from "svelte-utils/map";
import { SplitComponent } from "svelte-utils/top_bar_layout";
import BackButton from "./BackButton.svelte";
import { layerId, Link } from "./common";
Expand Down
3 changes: 3 additions & 0 deletions web/src/common/zorder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ const layerZorder = [
"one-ways",

// Contextual layers cover up most things
"context-simd",
"context-population-density",
"context-population-outline",
"context-traffic",
"context-los",
"context-existing-infra",
Expand Down
2 changes: 2 additions & 0 deletions web/src/context/ContextualLayers.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import BusRoutes from "./BusRoutes.svelte";
import CBD from "./CBD.svelte";
import POIs from "./POIs.svelte";
import Population from "./Population.svelte";
import RailwayStations from "./RailwayStations.svelte";
import RouteNetwork from "./RouteNetwork.svelte";
Expand All @@ -25,6 +26,7 @@
style:visibility={expand ? "visible" : "collapse"}
>
<POIs />
<Population />
<RailwayStations />
<BusRoutes />
<CBD />
Expand Down
129 changes: 129 additions & 0 deletions web/src/context/Population.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<script lang="ts">
import {
FillLayer,
hoverStateFilter,
LineLayer,
VectorTileSource,
} from "svelte-maplibre";
import { SequentialLegend } from "svelte-utils";
import { makeRamp, Popup } from "svelte-utils/map";
import { HelpButton, layerId } from "../common";
import { assetUrl } from "../stores";
let showSIMD = false;
let showDensity = false;
// Color ramp from https://www.ons.gov.uk/census/maps/choropleth, dark to light.
let simdColorScale = ["#080C54", "#186290", "#1F9EB7", "#80C6A3", "#CDE594"];
// The percentiles are [1, 100]. The 5 colors cover 4 each.
let simdLimits = [0, 20, 40, 60, 80, 100];
let densityColorScale = simdColorScale.toReversed();
// Use the same (slightly rounded) buckets as https://www.ons.gov.uk/census/maps/choropleth/population/population-density/population-density/persons-per-square-kilometre. TODO Adapt for Scotland.
let densityLimits = [0, 4700, 13000, 33000, 94000, 1980000];
</script>

<button class="secondary" on:click={() => (showSIMD = !showSIMD)}>SIMD</button>
{#if showSIMD}
<SequentialLegend colorScale={simdColorScale} limits={simdLimits} />
<p>Darker colours are more deprived</p>

<HelpButton>
<p>
This shows the Scottish Index of Multiple Deprivation (SIMD) from <a
href="https://www.data.gov.uk/dataset/1102bf85-ed49-440a-b211-da87e8d752eb/scottish-index-of-multiple-deprivation-simd-2020"
target="_blank"
>
2020 data
</a>
. SIMD combines different domains: income; employment; health; education, skills
and training; geographic access to services; crime; and housing.
</p>
</HelpButton>
{/if}

<button class="secondary" on:click={() => (showDensity = !showDensity)}>
Population density
</button>
{#if showDensity}
<SequentialLegend colorScale={densityColorScale} limits={densityLimits} />
<p>Darker colours are denser</p>

<HelpButton>
<p>
This shows population data from <a
href="https://www.data.gov.uk/dataset/1102bf85-ed49-440a-b211-da87e8d752eb/scottish-index-of-multiple-deprivation-simd-2020"
target="_blank"
>
2020 data
</a>
.
</p>
</HelpButton>
{/if}

<VectorTileSource
url={`pmtiles://${assetUrl("cnt_layers/population.pmtiles")}`}
>
<FillLayer
{...layerId("context-simd")}
sourceLayer="population"
manageHoverState
paint={{
"fill-color": makeRamp(
["get", "imd_percentile"],
simdLimits,
simdColorScale,
),
"fill-opacity": hoverStateFilter(0.7, 0.9),
}}
layout={{
visibility: showSIMD ? "visible" : "none",
}}
>
<Popup openOn="hover" let:props>
<p>
Data zone {props.id}
has {props.population.toLocaleString()}
people, and a SIMD rank of {props.imd_rank}, putting it in the {props.imd_percentile}
percentile.
</p>
</Popup>
</FillLayer>

<FillLayer
{...layerId("context-population-density")}
sourceLayer="population"
manageHoverState
paint={{
"fill-color": makeRamp(
["/", ["get", "population"], ["/", ["get", "area"], 1e6]],
densityLimits,
densityColorScale,
),
"fill-opacity": hoverStateFilter(0.7, 0.9),
}}
layout={{
visibility: showDensity ? "visible" : "none",
}}
>
<Popup openOn="hover" let:props>
<p>
Data zone {props.id}
has {props.population.toLocaleString()}
people, with a density of {Math.round(
props.population / (props.area / 1e6),
).toLocaleString()} people per square kilometer
</p>
</Popup>
</FillLayer>

<LineLayer
{...layerId("context-population-outline")}
sourceLayer="population"
paint={{ "line-color": "black", "line-width": 1 }}
layout={{
visibility: showSIMD || showDensity ? "visible" : "none",
}}
/>
</VectorTileSource>

0 comments on commit bb7a388

Please sign in to comment.