Published
Edited
Dec 22, 2020
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
state = cityst.split(", ")[1]
Insert cell
city = cityst.split(", ")[0]
Insert cell
function get_fips(k) {
if (master_map.get(k) === undefined) {return null}
return master_map.get(k).fips
}
Insert cell
sldl.objects['-'].geometries[0].properties
Insert cell
import { select } from '@jashkenas/inputs'
Insert cell
cities = new Set(redlines.objects.fullDownload.geometries.map(d => `${d.properties.city}, ${d.properties.state}`))
Insert cell
md`
The four redlining colors closely correspond to four of the standard bootstrap button colors. (red: danger, yellow: warning, blue: primary, green: success). Since web users will have internalized the meaning of those colors already, I just use the bootstrap equivalents instead of trying to glean them from the maps.

`
Insert cell
HOLC_bootstrap = ({"A": "#28a745", "B": "#17a2b8", "C": "#ffc107", "D": "#dc3545"})
Insert cell
import { toposimplify } from '@lemonnish/minify-topojson-in-the-browser'
Insert cell
{
const copy = JSON.parse(JSON.stringify(joint_topojson))
// const simp = toposimplify(copy)
const quant = topojson.quantize(copy, 1e3)
const sldl_arcs = new Set(quant.objects.sldl.geometries.map(d => d.arcs).flat(3).map(d => Math.abs(d)))
const redline_arcs = new Set(quant.objects.redlines.geometries.map(d => d.arcs).flat(3).map(d => Math.abs(d)))
return [...redline_arcs].filter(d => sldl_arcs.has(d))
}
Insert cell
joint_topojson.objects.sldl.geometries[0].properties
Insert cell
{
const proj = d3.geoAlbersUsa()
let sldl = topojson.mesh(joint_topojson, joint_topojson.objects.sldl)
let sldls = topojson.feature(joint_topojson, joint_topojson.objects.sldl)
let redlines = topojson.feature(joint_topojson, joint_topojson.objects.redlines)
proj.fitExtent([[0, 0], [width, width*.66]], redlines)
const ctx = canvas.getContext("2d")
ctx.clearRect(0, 0, width, width)
const path = d3.geoPath().projection(proj).context(ctx)
ctx.globalAlpha = .5
ctx.lineWidth = 5
ctx.strokeStyle = "grey"

ctx.beginPath()
path(sldl)
ctx.stroke()
for (let feature of redlines.features) {
ctx.beginPath()
ctx.fillStyle = HOLC_bootstrap[feature.properties.holc_grade]
path(feature)
ctx.fill()
//ctx.stroke()
}
ctx.fillStyle = "rgba(0, 0, 0, .6)"
ctx.font = 'bold 32px sans-serif'
for (let feature of sldls.features) {
const centroid = proj(d3.geoCentroid(feature))
ctx.fillText(+feature.properties.SLDLST, centroid[0], centroid[1])
}

}
Insert cell
topojson = require("topojson")
Insert cell
[...(d3.rollup(redlines.objects.fullDownload.geometries.filter(d => get_fips(d.properties.state) == get_fips(state) && d.properties.city == city), d => topojson.merge(redlines, d), k => k.properties.holc_grade)).values()]
Insert cell
redlines.objects.fullDownload.geometries[0].properties
Insert cell
joint_topojson = {
const state_redlines =
redlines.objects.fullDownload.geometries.filter(d => get_fips(d.properties.state) == get_fips(state) && d.properties.city == city)
// const redlines_json = {"type": "FeatureCollection", "features": state_redlines.map(d => topojson.feature(redlines, d))}
const redlines_json = geojson_redlines_for_city(city, state)
const state_sldl =
sldl.objects['-'].geometries.filter(d =>d.properties && get_fips(d.properties.STATEFP) == get_fips(state))

const sldl_json = {"type": "FeatureCollection", "features": state_sldl.map(d =>
topojson.feature(sldl, d))}

return topojson.topology({sldl: sldl_json, redlines: redlines_json})
}
Insert cell
geojson_redlines_for_city("Boston", "MA")
Insert cell
function geojson_redlines_for_city(city, state) {
const redlines_geometries =
d3.rollup(redlines.objects.fullDownload.geometries.filter(d => get_fips(d.properties.state) == get_fips(state) && d.properties.city == city),
d => {return {"type": "feature",
"properties": d[0].properties,
geometry: topojson.merge(redlines, d)}}, k => k.properties.holc_grade)
return {"type": "FeatureCollection", "features": [...redlines_geometries.values()] }
}
Insert cell
Insert cell
Insert cell
d3 = require("d3@v6", "d3-collection")
Insert cell
sldl.objects['-'].geometries[0].properties
Insert cell
redlines = {
const redlines = await FileAttachment("redlines.topojson").json()
// I've lived in several of these cities, and they are not different from
// each other. Haverhill and Brockton is debatable, but IDC.
const boston = new Set([
"Arlington","Belmont","Boston","Braintree","Brookline","Cambridge", "Chelsea","Dedham","Everett","Lexington","Malden","Medford","Melrose",
"Milton","Needham","Newton","Quincy","Revere",
"Saugus","Somerville","Waltham","Watertown","Winchester","Winthrop"])
for (let row of redlines.objects.fullDownload.geometries) {
if (row.properties.state == "MA" & boston.has(row.properties.city)) {
row.properties.city = "Boston"
}
}
return redlines
}

Insert cell
sldl = FileAttachment("quant@1.topojson").json()
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more