SB79 Transit Oriented Development Upzoning
About the Dataset
Senate Bill 79 (SB79) requires Metropolitan Planning Organizations (MPOs) to identify and map Transit-Oriented Development (TOD) Zones based on proximity to qualifying transit stops.
This project develops a reproducible geospatial methodology to:
- Identify SB79-eligible transit stops (Tier 1 and Tier 2)
- Define pedestrian access points and stations associated with those stops
- Generate distinct TOD zones based on Euclidean distance bands around access points
- Apply jurisdictional population rules
- Produce a policy-compliant TOD zone layer for the Bay Area
The resulting datasets will serve as the authoritative SB79 TOD geography for Alameda, San Francisco, San Mateo, and Santa Clara counties.
Project Scope:
- Data Collection – Gather GTFS feeds, Caltrans HQTS data, jurisdiction boundaries, and transit station datasets.
- Data Preparation / Modeling – Identify TOD-eligible stops, classify tiers, construct pedestrian access points, and generate TOD bands.
- Data Ingestion – Prepare final geospatial layer for internal review and publication.
- Data Catalog / Publishing / MDM – Document methodology, inventory dataset in MDM Catalog, add to Enterprise Database, and publish to DAAS platforms (e.g. ArcGIS Online, Open Data, Socrata.)
Resources
| Resource Type | Resource Name | Description | Source/Location | Format | Owner | Version | Date Acquired/Created | Dependencies | Usage Notes |
|---|---|---|---|---|---|---|---|---|---|
| Dataset | Pedestrian Access Points | Pre-defined pedestrian access points for transit agencies | Box Link | ZIP/Shapefile | MTC | Current | 2026-02-18 | None | Agency-specific access point locations |
| Dataset | Transit Stations | Transit station location data | Box Link | ZIP/Shapefile | MTC | Current | 2026-02-18 | None | Station geometries and attributes |
| API | 511 GTFS Data | Regional GTFS feeds for Bay Area transit agencies | Box Link | ZIP | MTC | Current | 2026-02-18 | None | Combined regional GTFS feed |
| Dataset | High Quality Transit Stops | Caltrans-defined major BRT stops and high-frequency transit | ArcGIS Online | Feature Service | MTC | Current | 2026-02-18 | None | Used to identify Tier 2 BRT stops |
| Dataset | Jurisdiction Boundaries | Bay Area city and county boundaries with population data | ArcGIS Online | Feature Service | MTC | Current | 2026-02-18 | None | Population rules and geographic scope |
Expected Fields
This process will generate four interrelated datasets:
SB79 Transit-Oriented Development Zones
Final policy-compliant TOD zone polygons with tier classifications and distance bands.
Field specifications to be documented during development.
Stations
Parent transit station locations (location_type = 1 in GTFS hierarchy).
Field specifications to be documented during development.
Stops
Individual transit stop/platform locations actively served by transit routes.
Field specifications to be documented during development.
Access Points
Pedestrian access locations for each transit station used as the basis for TOD zone generation.
Field specifications to be documented during development.
Running the Pipeline
The pipeline is implemented as a sequence of four Jupyter notebooks. Each notebook is self-contained and reads/writes to a shared GeoPackage (tod_database.gpkg) defined in config.py. Steps 2 and 3 are separated by a mandatory manual GIS review gate — do not skip it.
Prerequisites
- Python environment with
geopandas,pandas,gtfs_kit,shapely, anduuidinstalled - Access to the MTC Box folder containing source data (see Resources)
- Paths in
config.pyupdated to match your local data directory - QGIS (or equivalent) for the manual review step between Steps 2 and 3
Step 1 – GTFS TOD Stop Classification
Notebook: 1_gtfs_tod_stop_classification.ipynb
Loads the regional GTFS feed and Caltrans High Quality Transit Stops (HQTS) data, classifies each stop as TOD-eligible (Tier 1 or Tier 2), and writes the results to the shared GeoPackage.
Outputs written to GPKG:
tod_stops— all GTFS stops withtod_stopflag andtransit_tierclassificationstations— GTFS location_type=1 parent station records
No manual review required between Steps 1 and 2.
Step 2 – TOD Stop and Access Point Assignment
Notebook: 2_tod_stop_and_access_assignment.ipynb
Loads per-agency pedestrian access point datasets, normalizes and merges them into a single GeoDataFrame, joins GTFS-authoritative station_id values, then spatially assigns each TOD stop and access point to its nearest parent station using a distance-threshold buffer (EPSG:26910). Outputs both finalized layers and review layers flagging spatial conflicts and orphaned records.
Access point sources (loaded and normalized in order):
BA— BART (BART_PedAccessPoints_GTFS_v1.zip)CT— Caltrain (Caltrain_PedAccessPoints_GTFS_v3.zip)AC— AC Transit (AC_Transit_PedAcessPoints_v3.gdb)SC— VTA (VTA_PedAccessPoints_GTFS_v2.zip)SF— SFMTA (SFMuni_PedAccessPoints_GTFS_v1.zip)
Outputs written to GPKG:
tod_stops— TOD stops with spatially assignedstation_idtod_access_points— merged access points with spatially assignedstation_idtod_stops_review— stops with spatial conflicts or missing assignments (for manual review)tod_access_review— access points with spatial conflicts or missing assignments (for manual review)
Manual GIS review required before running Step 3.
- Open
tod_stops_reviewandtod_access_reviewin QGIS.- Inspect records with
valid_station_assignment = 0or conflicts.- Correct
station_idassignments as needed and setvalid_station_assignment = 1for resolved records.- Save the corrected layers back to the GeoPackage as
tod_stops_review_v1andtod_access_review_v1.
Re-running Step 2 will overwritetod_stops_reviewandtod_access_reviewbut will never touch the_v1layers.
Step 3 – Station Assignment Reintegration
Notebook: 3_tod_station_assignment_reintegration.ipynb
Reads the manually reviewed _v1 layers, merges corrections back into the main tod_stops and tod_access_points layers, and re-exports the final corrected versions to the GeoPackage.
Inputs read from GPKG:
tod_stops_review_v1— manually corrected stops review layertod_access_review_v1— manually corrected access points review layer
Outputs written to GPKG:
tod_stops— final stops with all corrections appliedtod_access_points— final access points with all corrections applied
No manual review required between Steps 3 and 4.
Step 4 – TOD Zone Buffer Generation
Notebook: 4_tod_zone_buffers.ipynb (planned)
Generates 200 ft, ¼ mile, and ½ mile Euclidean buffer zones around finalized access points, applies the policy matrix (tier precedence, jurisdictional population rules, geographic scope), and produces the final SB79 TOD Zone polygons.
Outputs written to GPKG:
tod_zones— final SB79 TOD Zone polygons with tier and distance-band attributes
Process Overview
This section describes the conceptual methodology behind the pipeline. For step-by-step execution instructions, see Running the Pipeline.
Manual Data Preparation
- Manually create stations for stops that will be flagged as TOD applicable, such as SFMTA light rail stops not co-located with a BART Station (e.g. Van Ness, Church, Forest Hill, Yerba Buena/Moscone, etc.), VTA light rail stops, and BRT stops.
- Manually create pedestrian access points for stops that will be flagged as TOD applicable following the same process as above (add guidance from HCD on what constitutes a pedestrian access point, e.g. crosswalks, sidewalks, etc.).
Load Data and Libraries
- Set up environment and load necessary libraries (e.g., pandas, geopandas, gtfs_kit)
- Load GTFS data using gtfs_kit and convert to GeoDataFrame for spatial analysis
- Load pedestrian access point data and transit station data as GeoDataFrames
- Load Caltrans High Quality Transit Stops (HQTS) data as GeoDataFrame
Prepare Data for Analysis
- Enrich GTFS stops with route and agency information by merging with routes and agency tables; aggregate to get lists of routes and agencies serving each stop
- Filter GTFS stops to include only those served by relevant transit agencies (e.g., BART, Caltrain, AC Transit, SFMTA, VTA)
- Separate stations and stops based on GTFS hierarchy based on location_type and parent_station fields (see GTFS documentation for details)
- Filter Caltrans High Quality Station Stops to include only those with
HQTA Type == major_stop_brt
Flag Transit-Oriented Development (TOD) Stops
- Flag GTFS stops as TOD applicable if they are either:
- A stop that meets the Caltrans definition of a major BRT stop (i.e., in the filtered Caltrans dataset) using a list of
stop_ids from the filtered HQTS dataset, OR - A stop with
route_type in [0 (Tram, Streetcar, Light rail), 1 (Subway, Metro)](see GTFS documentation for details) oragency_id == 'CT' (Caltrain)- Exceptions: Exclude stops South of Tamien Station on the Caltrain System, and BART stops within Contra Costa County.
- A stop that meets the Caltrans definition of a major BRT stop (i.e., in the filtered Caltrans dataset) using a list of
- Create Transit Tier classification:
- Tier 1:
route_type == 1 (Subway, Metro)oragency_id == 'CT' (Caltrain) - Tier 2:
route_type == 0 (Tram, Streetcar, Light rail)or a stop that meets the Caltrans definition of a major BRT stop (i.e., in the filtered Caltrans dataset) using a list ofstop_ids from the filtered HQTS dataset.
- Tier 1:
- Create a final filtered GeoDataFrame of TOD applicable stops, including relevant attributes such as stop_id, stop_name, parent_station, agency_name, route_short_name, and geometry.
Associate Parent Stations with TOD Stops & Access Points
- Associate stops and access points with parent stations. This may be performed by spatially joining stops and access points to stations using a near spatial join with a specified distance threshold (e.g. 200 feet) though manual review and adjustments will likely be necessary to ensure accurate associations, especially in dense urban areas where multiple stations and stops may be in close proximity.
Create Transit-Oriented Development (TOD) Zones
- Generate 200 ft, .25 mile, and .5 mile Euclidean (straight-line) buffers around all pedestrian access points by tier
- Intersect buffers with jurisdiction boundaries with associated population data to determine applicable zones based on the policy matrix
- Remove .5 mile buffers where jurisdiction population is ≤ 35,000 or in unincorporated areas
- Erase Tier 2 areas where overlapping with Tier 1 buffers to ensure Tier 1 precedence
- Dissolve by Tier and distance band to create final TOD Zone geometries
- Validate and review final TOD Zone geometries for accuracy and consistency with the defined criteria
Development Notes
SB79 TOD Zones – Policy Applicability Matrix
This table summarizes where Transit-Oriented Development (TOD) Zones apply by Transit Tier and Jurisdiction Type. Distances are measured from pedestrian access points and represent distinct distance bands.
Where TOD Zones Apply
| Tier | City with Population > 35,000 | City with Population ≤ 35,000 | Unincorporated Area |
|---|---|---|---|
| Tier 1 | 0–200’ 201’–1320’ 1321’–2640’ |
0–200’ 201’–1320’ |
Not Applicable |
| Tier 2 | 0–200’ 201’–1320’ 1321’–2640’ |
0–200’ 201’–1320’ |
Not Applicable |
Policy Constraints
- Tier Precedence Rule:
- Where Tier 1 and Tier 2 zones intersect, Tier 1 supersedes Tier 2. Tier 2 geometry must be erased in overlapping areas.
- Geographic Scope:
- Applies only to cities located within:
- Alameda County
- San Francisco County
- San Mateo County
- Santa Clara County
- Applies only to cities located within:
- Distance Bands:
- Bands are distinct (non-cumulative):
- 0–200 feet
- 201–1320 feet (¼ mile ring excluding first 200 feet)
- 1321–2640 feet (½ mile ring excluding first ¼ mile)
- Bands are distinct (non-cumulative):
Technical Considerations
- GTFS data provides the authoritative source for transit stop locations and service patterns
- Agency filtering focuses on relevant Bay Area operators: BART (BA), Caltrain (CT), AC Transit (AC), VTA (SC), and SFMTA (SF)
- Parent-child relationships in GTFS hierarchy distinguish between stations (location_type=1) and individual stops/platforms (location_type=0)
- Manual review required for complex station areas with multiple access points