Skip to content

Concepts

A bikescore-bna run is a pure function of its inputs and a config, executed by the pipeline. Five nouns describe the whole library — a city, its inputs, a config, the pipeline, and the score_city function that runs it — one per section below. Understanding them is enough to use it.

City

A CityIdentity is static regional metadata — name, slug, region, country, and (for US cities) a Census FIPS code. It drives acquisition (which boundary, OSM extract, census, and employment data to fetch) but is not itself a scoring input. It is typically stored as a city.toml file and loaded with load_city(dir).

Inputs

The raw files the pipeline consumes, as a dict[str, Path]:

name what source
osm OSM PBF clipped to the city boundary Geofabrik
boundary city boundary polygon (GeoJSON) US Census / Nominatim
census 2020 census blocks (population) US Census (pygris)
lodes_main, lodes_aux LODES employment (jobs) US Census LODES

acquire_city produces this dict; you can also assemble it by hand from files you already have.

Config

A BNAConfig is the effective, fully-resolved set of knobs the stages read — stress thresholds, imputation defaults, scoring weights, destination catalogs, and the LTS decision rules. You never construct it directly; you call build_config:

build_config()                 # library defaults
build_config("default")        # the bundled standard-BNA scenario
build_config("my.yaml")        # a scenario file you authored
build_config("default", {"city.default_speed": 40})  # with overrides

A scenario is a YAML document describing a config layer — the rules, catalogs, and overrides that make a run mean something. build_config resolves a scenario into a BNAConfig. See Extensibility.

Pipeline

The fixed, ordered list of eleven stages:

parse → census → jobs → attributes → segment → stress
      → graph → connectivity → destinations → scores → neighborhood

Each stage is a StageSpec: a name, its upstream dependencies, the dataset inputs it needs, a version, and a compute callable that reads files from upstream directories and writes files into its own output directory. bikescore-bna ships PIPELINE as a static list; the same depends_on metadata is enough for a larger tool to re-derive a DAG from it.

score_city

The database-free driver: it runs every stage in PIPELINE order into a workdir you choose (default a timestamped folder under ./bikescore-bna-runs/), wiring each stage's inputs from prior outputs, and returns a ScoreResult mapping each stage to its output directory. There is no SQLite, no hashing, and no run store — score_city simply runs the stages in order and leaves their outputs on disk for reuse (ScoreResult.from_dir rebuilds a result from such a folder).

result = score_city(inputs, config)
scores = result.output("scores", "scores.parquet")