Detailed Methodology: Depave Bridgeport
This document describes the Bridgeport, Connecticut implementation of the Depave pipeline in sufficient detail for a GIS analyst to reproduce or extend the analysis. Bridgeport runs the same generic pipeline path as Fort Lauderdale, with a different pavement source and a simpler set of inputs. Source code, configuration files, and the other city pipelines for comparison live in a single repository; paths below are relative to the repository root.
1. Scope & study area
The analysis covers the municipal boundary of the City of Bridgeport, Connecticut (Fairfield County). All spatial operations are carried out in EPSG:2234 (NAD83 / Connecticut, US survey feet), the Connecticut State Plane standard. It is suited to metric operations such as area, distance, and buffer across the study area. Web exports are reprojected to EPSG:4326 for MapLibre consumption.
Tract-level summaries use the 2020 TIGER/Line census tracts. The statewide Connecticut file is filtered to Fairfield County (COUNTYFP = 001), then clipped to the municipal boundary. Tracts whose clipped area is less than 50% of their original extent are dropped as edge slivers. After filtering, 38 census tracts remain inside the city.
The study-area and location selection is configuration-driven (config/locations/bridgeport.yaml, config/study_areas_bridgeport.yaml). The orchestrator dispatches on the DEPAVE_LOCATION environment variable. Any value other than nyc runs the generic (Fort Lauderdale-style) path, so Bridgeport reuses that code with its own configuration.
2. Deviations from the Fort Lauderdale pipeline
Bridgeport shares the generic pipeline path with Fort Lauderdale but substitutes several inputs. The biggest change is the pavement source: Fort Lauderdale classifies raw NAIP imagery with an in-house random forest, while Bridgeport consumes a land-cover raster that NOAA has already classified.
| Step | Fort Lauderdale | Bridgeport |
|---|---|---|
| Pavement source | NAIP 1 m 4-band imagery, classified in-house by a self-supervised random forest | NOAA C-CAP High-Resolution Land Cover (1 m, 2016); impervious class selected directly, no classifier |
| Core/non-core cut | Hybrid FDOT RCI surveyed widths (state roads) + OSM class-estimated widths (local roads) + OSM sidewalks | OSM-only widths (lane-count and class-based estimates) + OSM sidewalks; no surveyed-width dataset staged |
| Flood layer | DEM proxy, three-component: depression depth + D8 flow accumulation + inverse SSURGO Ksat | DEM proxy, two-component: depression depth + D8 flow accumulation (no soil data); delivered as raster tiles |
| Heat layer | NOAA/CAPA 2021 surface-temperature polygons (mobile-traverse campaign) | Landsat 9 land-surface-temperature raster (~100 m), zonal mean per tract |
| Canopy layer | University of Miami lidar-derived canopy polygons | ESA WorldCover tree class (class 10), per-tract tree-pixel fraction |
| Equity overlay | CEJST v2.0 (federal Justice40 designation); EJScreen when available | CEJST v2.0 (federal Justice40 designation); no separate EJ layer |
| Processing CRS | EPSG:2236 (NAD83 / FL East, ftUS) | EPSG:2234 (NAD83 / Connecticut, ftUS) |
Because the impervious class is pre-labeled in C-CAP, the classify stage (the NAIP random-forest classifier) is skipped for Bridgeport. The location config sets use_naip_classification: false and the orchestrator gates the stage accordingly. Downstream stages (needs scoring, stacked composite, equity overlay, web export) are shared between locations and unmodified.
3. Data sources
Inputs are taken from config/data_sources_bridgeport.yaml. Several layers (the municipal boundary, the C-CAP raster, the Landsat LST raster, and the DEM) are pre-staged from a local data library rather than fetched from a remote endpoint. The CRS values for the C-CAP, LST, and DEM rasters were additionally verified against the raster headers.
| Dataset | Resolution / vintage | Native CRS | Source |
|---|---|---|---|
| Bridgeport municipal boundary | Single polygon / current | EPSG:4326 | Local stage (municipal_boundary.geojson) |
| Census tracts | 2020 TIGER/Line, statewide CT filtered to Fairfield County (COUNTYFP 001) | EPSG:4269 | Census Bureau (tl_2020_09_tract.zip) |
| Parcels (PLUTO analog) | CT CAMA tax roll / 2025 | EPSG:4326 | CT GIS Office statewide CAMA filtered to Bridgeport; field State_Use |
| Pavement land cover | NOAA C-CAP High-Res 2016, 1 m | EPSG:26956 (NAD83 / CT, meters) | NOAA C-CAP; class 2 = Impervious (ccap_1m_landcover.tif) |
| Buildings | MS US Building Footprints v2, 2022 | EPSG:4326 | Microsoft (ms_buildings.gpkg) |
| OSM core features | Current snapshot | EPSG:4326 | Overpass API: highway ways, footway=sidewalk |
| Tree canopy | ESA WorldCover class 10, 10 m, 2021 | EPSG:4326 | ESA WorldCover tree class → canopy_worldcover.tif |
| Heat (surface T) | Landsat 9 ST_B10 summer composite, ~100 m | EPSG:2234 | Local LST raster (landsat_lst_celsius.tif) |
| 3DEP lidar DTM | 1 m native, resampled to 10 ftUS (~3 m) | EPSG:2234 | USGS 3DEP (dem_10m.tif) |
| SSURGO Ksat | Not staged for Bridgeport | EPSG:4326 | NRCS Soil Data Mart; absent here → two-component proxy |
| CEJST v2.0 | Tract-level, archived mirror | EPSG:4269 | Public Environmental Data Partners mirror; field SN_C |
| EJScreen 2024 | Block-group, optional | — | EPA gaftp.epa.gov (supplement; not used for the equity flag here) |
| FEMA NFHL | Regulatory zones (Fairfield County) | EPSG:4269 | FEMA; reference only, not a needs layer |
4. Pavement extraction (C-CAP class selection)
Bridgeport does not run the NAIP random-forest classifier that Fort Lauderdale uses. The pavement source is the NOAA C-CAP High-Resolution Land Cover for coastal Connecticut, a 1-meter raster already classified into land-cover classes, 2016 vintage. The native CRS is EPSG:26956 (NAD83 / Connecticut, meters). Extraction is class selection plus building subtraction plus geometry cleanup, implemented in src/depave/process/pavement_ftl.py (extract_pavement_ftl).
Class selection
C-CAP class 2 is Impervious Surface. The raster is masked to the study area, and pixels equal to the built class (value 2) are selected. The impervious class covers hard surfaces broadly, so it includes pavement and rooftops. Two land-cover categories that frequently produce false positives in coarser products are not conflated with pavement here: bare land and developed open space (lawns) carry their own C-CAP classes and are excluded by selecting class 2 alone.
Building subtraction and cleanup
Because the impervious class includes roofs, building footprints are differenced out to isolate ground-level pavement. The Microsoft US Building Footprints layer (v2, 2022 vintage, clipped to Bridgeport) is unioned and subtracted from the polygonized impervious surface. The remaining geometry is reprojected to EPSG:2234, cleaned with a buffer(0) pass, exploded into single parts, simplified to a fixed tolerance, and filtered to drop polygons below 100 square feet.
No machine learning is involved at this stage. Because the labels come pre-assigned from NOAA, the accuracy ceiling is set by the C-CAP product itself rather than by a locally trained model. C-CAP is 1 m and pre-classified, finer than the 10 m WorldCover built-up class it replaced for this city, but it is a 2016 snapshot and it cannot distinguish asphalt from concrete. Building subtraction depends on the 2022 Microsoft footprints, so structures built between the two vintages may be handled imperfectly.
5. Core vs non-core classification
Core/non-core classification uses the same module as Fort Lauderdale (classify_core_noncore_ftl in src/depave/process/pavement_ftl.py), with simpler inputs. "Core" pavement is the pavement a city needs: travel lanes, sidewalks, and formal parking. "Non-core" is the pool of depave candidates. Each pavement polygon is both intersected with and differenced against the core mask, so a connected road blob is split rather than tagged wholesale.
Core mask construction
Bridgeport has no surveyed road-width dataset. Where Fort Lauderdale folds in FDOT Roadway Characteristics Inventory measured widths for state roads, Bridgeport relies entirely on OpenStreetMap. This is the main simplification relative to the Fort Lauderdale core mask.
- Highways are buffered by a per-feature half-width. When the OSM
lanestag is present, the half-width ismax(lanes, 1) × 10 ftper side. Otherwise a per-class fallback applies (for example motorway/trunk 30 ft, primary 25 ft, secondary 20 ft, tertiary 15 ft, residential 12 ft, with a 10 ft default). Service, track, driveway, footway, path, cycleway, bridleway, steps, and corridor are excluded from the core mask; these become non-core candidates. - Sidewalks (
footway=sidewalk) are buffered by 4 ft on each side.
Parking is non-core. Parking pavement falls outside the road-and-sidewalk core mask, so it is classified non-core, the same as the other cities. No explicit parking layer is used.
6. Needs scoring
All four needs layers score the clipped set of 38 census tracts. Each returns a *_raw column and a min-max-normalized *_score column in [0, 1], where higher means more need. Scoring is implemented in the shared needs stage.
Heat
The heat layer is a Landsat 9 land-surface-temperature composite (thermal band ST_B10, summer), staged as a raster in EPSG:2234 at roughly 100 m resolution. Each tract's heat value is the zonal mean land-surface temperature within the tract, min-max normalized across the tract set to produce heat_score. There is no ground-truth mobile-traverse campaign for Bridgeport, so the heat layer is coarser than Fort Lauderdale's CAPA-derived surface.
Stormwater flood risk (DEM proxy)
Implemented in src/depave/process/stormwater_proxy.py. Bridgeport runs the two-component, terrain-only variant. The three-component variant requires SSURGO saturated hydraulic conductivity (Ksat), which is not staged for Bridgeport, so the soil term is dropped. Pipeline:
- Clip the 3DEP DTM (1 m native, resampled to 10 US survey ft ≈ 3 m pixels) to the study area; mask nodata.
- Gaussian pre-smoothing (σ = 1.5 px) to erase tile-boundary micro-cliffs, where sub-meter elevation offsets between adjacent lidar tiles would otherwise be read as real sink edges.
- Priority-flood depression fill on the smoothed DEM (via
richdem, with pysheds and pure-numpy fallbacks). - Depression depth =
filled_smoothed − original_dem, clipped to ≥ 0. The depth is measured against the un-smoothed original, so a real sink stays visible after the blur. - D8 flow accumulation on the filled DEM, log-transformed (
log1p) because the distribution is heavy-tailed. - Each field is percentile-rank-normalized to [0, 1], then combined with the two-component weights.
score = 0.6 × depression + 0.4 × flow_acc # two-component, terrain only
Depression carries the most weight because surface ponding is the most direct pluvial signal on flat terrain. Tier breaks at the 50th / 75th / 90th percentile of non-zero composite pixels produce limited / moderate / extreme classes. The breaks are within-city percentiles, so a fixed share of the wettest pixels always lands in each tier. The tiers rank relative wetness inside Bridgeport; they do not express an absolute flood depth or return period.
The tier raster is published as raster map tiles for web display. Polygonizing and simplifying the dissolved per-tier MultiPolygons exhausted memory on smaller machines, so the display layer is served as a raster rather than vectors. A dissolved per-tier polygon version is still produced internally and feeds the per-tract flood score.
Per-tract flood score is the weighted sum of tier coverage, then rescaled across the 38 tracts:
flood_raw = 0.5 · pct_extreme + 0.3 · pct_moderate + 0.2 · pct_limited
flood_score = minmax(flood_raw) # rescaled relative to the other 37 tracts
This layer is a relative ranking of rainfall-ponding potential, and it has not been validated against observed flooding. It is topography-only: no soil term, no storm-drain capacity, no rainfall depth or intensity, no tides, no groundwater. Bridgeport is a coastal city, and this proxy does not capture coastal, tidal, or storm-surge inundation; it targets pluvial (rainfall) ponding alone. FEMA NFHL zones are retained for reference only and are not used as the flood-needs layer. Read the tiers as a screen for where to look first, not a forecast of where water will stand.
Canopy deficit
Canopy comes from the ESA WorldCover tree class (class 10), burned to a raster, rather than from C-CAP. For each tract the canopy percentage is the tree-pixel fraction; the deficit is 1 − canopy_pct; the normalized score is a min-max rescaling across the tract set.
Pavement burden
Per-tract non-core pavement fraction = (tract ∩ non-core pavement union).area / tract.area, min-max normalized.
7. Stacked composite
Equal-weight mean of the four normalized scores (no per-dimension weighting is configured for Bridgeport):
stacked_score = mean(heat_score, flood_score, canopy_score, pavement_score)
Priority tracts are those at or above the 75th percentile of stacked_score (top quartile). A second column, n_high_needs, counts how many of the four dimensions a tract is simultaneously in the top quartile for, which is useful for context. Implemented in stacked_needs.py. For Bridgeport, 10 of 38 tracts (about 26%) are flagged as priority.
8. Equity overlay
Implemented in equity_overlay.py, reused from the NYC pipeline. The orchestrator passes the CEJST disadvantaged subset (field SN_C == 1, from the v2.0 archived mirror) as the dac argument; the separate city-EJ argument is an empty GeoDataFrame, since Bridgeport has no separate EJ layer. A tract is flagged is_dac if it overlaps the CEJST disadvantaged union by at least 1% of its area. Bridgeport has 33 CEJST-disadvantaged tracts, and 10 of the 10 priority tracts are also disadvantaged. Aggregate statistics (non-core acreage in priority tracts, in disadvantaged priority tracts, and so on) are written to the processed summary file.
9. Known limitations
- C-CAP coarseness and class semantics. The pavement source is 1 m, pre-classified, and its class 2 (Impervious) lumps pavement and roofs together. Building-footprint subtraction is the only roof removal. C-CAP cannot distinguish asphalt from concrete. This is a published land-cover product, not a city-specific classifier like NYC's or Fort Lauderdale's.
- C-CAP vintage is 2016. It is older than the 2020 tracts and the 2022 building footprints. Land-cover change since 2016 is unmodeled, and new construction may leak into or out of the pavement layer at the seams between vintages.
- Core mask uses OSM widths only. Bridgeport has no surveyed road-width layer, so the core/non-core split relies on OSM lane counts and class-based width estimates. Width errors and OSM completeness gaps propagate directly into the split.
- Stormwater proxy is two-component and topography-only. With no SSURGO soil term and no hydraulic model, it is a terrain screen for rainfall ponding. It omits soil permeability, storm-drain capacity, rainfall depth, tides, and groundwater, and it is not validated against observed flooding.
- Coastal and tidal flooding is not captured. Bridgeport is a coastal city, but the proxy addresses pluvial ponding only. Coastal, tidal, and storm-surge inundation are out of scope, and FEMA NFHL is reference-only.
- Heat layer is coarse. A single-band Landsat 9 surface-temperature composite at roughly 100 m, summarized as a zonal mean, has lower spatial fidelity than a ground-truthed traverse campaign.
- Small sample size. 38 tracts is a small denominator for min-max normalization and percentile tiers. A single outlier tract can move scores noticeably. Read the results as relative rankings within Bridgeport; their absolute magnitudes are not meaningful on their own.
- CEJST archival status. The official CEJST endpoint was taken offline in January 2025; we mirror v2.0 from Public Environmental Data Partners. If the mirror structure changes,
config/data_sources_bridgeport.yamlneeds updating.
10. Reproducibility
Full run from scratch
export DEPAVE_LOCATION=bridgeport
python3 scripts/run_pipeline.py \
--study-area bridgeport \
--stages all
Stage names: study_area, acquire, classify, pavement, needs, equity, export. Any comma-separated subset is accepted. The classify stage auto-skips because use_naip_classification: false in config/locations/bridgeport.yaml; Bridgeport's pavement comes from the pre-classified C-CAP raster, so no NAIP classifier runs.
Outputs
data/bridgeport/interim/pavement_classified.gpkg: polygons withpavement_type ∈ {core, non-core}data/bridgeport/interim/stormwater_proxy.gpkgandstormwater_tiers.tif: tier polygons and the raster served as map tilesdata/bridgeport/processed/stacked_needs.gpkg: scored tractsdata/bridgeport/processed/equity_overlay.gpkg: scored tracts +is_dac,is_prioritydata/bridgeport/processed/summary_stats.json: headline numbersdata/bridgeport/processed/*.geojson: web-ready layers (pavement, non-core, flood zones, tracts, priority), plus raster tiles for the stormwater tiers
11. Credits & citation
Depave Bridgeport is produced by ONE Architecture & Urbanism, Inc. The methodology extends the DepaveLA/DepaveNYC framework with open-data substitutions appropriate to a city without NYC-grade municipal GIS products.
Data providers: NOAA Office for Coastal Management (C-CAP), USGS 3DEP, Microsoft (US Building Footprints), OpenStreetMap contributors, ESA WorldCover, USGS/NASA Landsat, U.S. Census Bureau, NRCS, FEMA, Connecticut GIS Office, and Public Environmental Data Partners (CEJST mirror). OpenStreetMap data are licensed under ODbL.
Suggested citation: Depave Bridgeport: A Screening Analysis of Non-Core Pavement and Environmental Need. ONE Architecture & Urbanism, 2026.