Context for AI assistants and contributors working in this repository.
Cities for Children — Beer Sheva streetscape accessibility. Interactive map and GIS pipeline measuring how reachable everyday services and child-relevant features are on foot from residential buildings. Collaboration between Urban95 and NUR.
- Live site: https://negevurbanresearch.github.io/urban95/
- Upstream repo: https://github.com/NegevUrbanResearch/urban95
- Python GIS pipeline (
src/) — ingests raw GeoJSON underdata/(and optionalfiltered/), calls Mapbox for walking isochrones, computes Urban95 (methodology weights) and Amenities Focus (expanded) scores, writes full-precision artifacts tooutput/and simplified GeoJSON/JSON underdocs/data/for the web app. - Static map site (
docs/) — HTML/CSS/JS only (no bundler). MapLibre GL, Turf, deck.gl, Chart.js loaded from CDNs indocs/index.html. Data paths are relative (BASE = "./data"indocs/app.js).
From the repository root (the dev server maps docs/data/ to the map’s relative ./data requests, matching BASE = "./data" in docs/app.js):
pip install -r requirements.txt
npm install
npm run startOpen http://localhost:8080/docs/index.html
npm run start:docs serves only docs/; relative ./data URLs in app.js will not resolve unless you change BASE or mirror assets.
-
Use a venv (
.venv/is gitignored). -
Install:
pip install -r requirements.txt -
Preprocessing needs a Mapbox token in a root
.envfile:mapbox_access_token=YOUR_TOKEN
Optional tuning: INDEX_SCORE_WORKERS (Urban95 scoring), ISOCHRONE_FETCH_WORKERS (isochrones stage).
$env:PYTHONPATH="src"
python scripts/seed_provisional_raw.py
python -m pipeline check- Optional (usually first if you use it):
python -m optional.filter— clips layers intofiltered/(legacy helper;filtered/is deprecated as a pipeline input — resolve fromdata/raw/viacore/paths.py). - Raw GIS under
data/raw/as registered insrc/core/paths.py(seepython -m pipeline check), plus shade SI underdata/raw/arcgis_shade/, anddata/raw/amenities_clean.geojsonfor the clean manifest. python -m pipeline run shade— validates raw ArcGIS SI inputs, writes metric prepared scoring layers tooutput/shade_si/, calibration tooutput/shade_si_calibration.json, and a simplified web-onlydocs/data/shade_si.geojson(+.gz). Run before building accessibility scoring.python -m pipeline run all(or stage-by-stage:isochrones→amenity_metrics→score→export_web) — writesoutput/buildings_scored.geojsonand publishes web layers viastages/export_web.pyfor its owned layers; shade and neighborhoods retain their separate publication ownership.python -m pipeline run rescore— recompute Urban95 weighted columns (incl. shade SI) on existing published buildings without Mapbox/isochrones. Refreshes buildings (+gz), lookup (+gz), and companion publish layers (amenities_new,street_lights,amenities_all,trees,parks,isochroneswhen available) viaexport_web; rerunpython -m pipeline run neighborhoodsimmediately afterward.python -m pipeline run neighborhoods— requires building-level outputs indocs/data/; updates neighborhoods GeoJSON,neighborhood_charts.json,citywide_stats.json.- Roads + spatial syntax (optional):
python -m optional.download_osm_roads→docs/data/roads.geojson, thenpython -m optional.generate_spatial_syntax→ segment/zone GeoJSON underdocs/data/.
The commands, filenames, schemas, and browser URL contracts are unchanged. During run all, named source frames are prepared/reused once; amenity and score work uses exact layer-by-layer/chunked reductions; street-light coverage uses exact threaded local unions; neighborhoods reuses one IDW geometry plan; and publication serializes each web layer once. Standalone stages keep their existing disk fallbacks. Neighborhoods intentionally rereads the rounded published building geometry so aggregates match the browser payload.
PIPELINE_FORBID_MAPBOX=1 is an acceptance-only guard for a warm run. It validates the complete (building_id, minutes) aggregate and aborts before token/session/network work if any key is missing. With the variable unset, the existing Mapbox token/cache/API behavior remains in force.
Publication ownership is recorded in docs/data/README.md: export_web owns buildings + lookup, amenities_new, street_lights, amenities_all, trees, parks, isochrones and their specified gzip companions; shade owns shade_si and its gzip; neighborhoods owns neighborhoods.geojson, neighborhood_surface.geojson, neighborhood_charts.json, and citywide_stats.json.
foliumis inrequirements.txtbut is not imported by any file undersrc/(may be legacy or notebook use).
- Entry:
docs/index.html,docs/app.js,docs/style.css. - Data URLs are defined at the top of
docs/app.js(BUILDINGS_URL,AMENITIES_*,ISOCHRONES_URL, neighborhoods, charts JSON, etc.). Filenames there must match what the pipeline produces (or what you commit). - Icons: runtime loads from
./iconsrelative to the published site →docs/icons/. There is also a top-levelicons/directory; the app usesdocs/icons/viaICONS_BASE. - Some layers support optional
.gzfetch viafetchJsonWithGzipFallback. - GitHub Pages: publish from the
docs/folder..gitignoreun-ignoresdocs/data/for deployment, butdocs/data/buildings_accessibility.geojsonis explicitly ignored — most generated GeoJSON underdocs/data/is intended to be committed; verifygit statusfor this repo’s current rules.
| Path | Role |
|---|---|
docs/ |
Static site + data/ JSON/GeoJSON consumed by the map |
src/ |
Preprocessing and scoring scripts |
data/ |
Raw GIS inputs (gitignored empty checkout common) |
output/ |
Full-precision pipeline outputs (gitignored) |
filtered/ |
Legacy clipped outputs only (gitignored; deprecated as pipeline input) |
src/ packages: pipeline/ (CLI), core/ (paths, preflight, geo_io, geojson_utils), stages/ (shade, isochrones, amenity_metrics, urban95_scoring, export_web, neighborhoods, rescore), lib/ (shade_si, urban95_weights, buildings_prep, buildings_lookup, amenity_layers), optional/ (filter, download_osm_roads, generate_spatial_syntax, export_urban_nature_areas).
- No
pyproject.toml, Docker, Makefile, ESLint/Prettier/Ruff configs, or.github/workflowswere present whenAGENTS.mdwas written — confirm with a quick directory listing if that matters for your change. .gitignoreexcludes.venv/,data/,output/,filtered/,node_modules/,.env, with an exception sodocs/data/can be tracked for Pages (see Frontend above for thebuildings_accessibility.geojsoncarve-out).
- Urban95: weighted category/subcategory model; weights and category functions live in
lib/urban95_weights.py, attached bystages/urban95_scoring.py(python -m pipeline run score; see README for percentages). - Shade (Environmental Quality sub-score): uses Beer Sheva BDAR
summer_SIfrom Derech Tzel (shading metrics guide PDF) as-is — SI, not SAI, not recalculated. Building SI = 300 m area-weighted meansummer_SIaround each building footprint (near-edge buffer), then stored/displayedsummer_siis rounded to 1 decimal place with standard half-up ties before scoring/output (0.15 → 0.2,0.35 → 0.4). Official SI interpretation buckets are<0.10 severe lack,0.10–<0.20 significant lack,0.20–<0.40 needs improvement,0.40–<0.60 good shade,≥0.60 excellent shade. Urban95 keeps a project-specific ternary sub-score mapping on that rounded building SI:<0.20 → 0,0.20–<0.40 → 50,≥0.40 → 100. Scoring source: prepared layers inoutput/shade_si/. Web display only: simplifieddocs/data/shade_si.geojson(+ gzip). Other Urban95 fixed-distance subcategory rules (trees, parks, lights, family services, etc.) likewise measure from the building footprint edge, not the centroid. Amenities Focus isochrones remain centroid-originated. - Amenities Focus (
expanded): amenity-count-style model tied closely to amenity filters in the UI.
For field names and _5min/_10min/_15min columns, follow README.md and the columns referenced in docs/app.js.
When changing data contracts, update both the Python writers and docs/app.js URL constants (and gzip behavior if applicable). When changing scoring, coordinate lib/urban95_weights.py with stages/urban95_scoring.py / stages/export_web.py and verify downstream aggregates if neighborhood/citywide stats depend on new columns.