Inspiration

When a water main breaks, crews isolate it by closing the nearest valves. That only works if the valves turn. The City of Houston's own GIS records mark 17,413 valves on water mains as inoperable: seized, buried, or "cannot locate". Each dead valve forces crews out to the next ring of valves, and the outage spreads to homes, businesses and fire hydrants that should never have lost water. I wanted to show that cost on Houston's real network, and turn it into a repair list.

What it does

Click any main in Houston, or search a street corner or address, and ValveRank breaks it. It then shows three outcomes side by side:

  • Every valve works: the smallest outage crews could achieve.
  • City valve records: the outage given which valves the City records as inoperable.
  • After the top 100 repairs: the outage once ValveRank's recommended repairs are done.

Each break has a timeline: gushing, then still gushing while crews reach a working valve, then shut off for repair. Sliders set the break size and response times. The Fix plan ranks dead valves by the customer-hours their repair would win back. The Evidence view shows the City data and real 311 break calls behind the model.

Citywide, dead valves make neighborhood shut-offs 2.4× worse (1.07 M → 2.57 M customer-hours a year). In the worst case, one dead valve turns a 1-customer shut-off into 2,496. Repairing the right 100 valves wins back 41% of the 4.26 M customer-hours a year that dead valves cost.

How I built it

  • Data: City of Houston public GIS. 290,959 mains, 166,362 valves, 62,540 hydrants and 544,011 customer accounts, cross-checked against Houston Public Works financial reports (mains within 1%, hydrants within 0.1%).
  • Isolation segments: pipes become a graph; valves become cut points. A union-find pass gives the 72,171 smallest shut-off areas if every valve works, and 55,006 once inoperable valves can't close.
  • Downstream supply loss: one articulation-point pass (Tarjan) over the segment graph finds every area cut off from all 218 plants, pump stations and tanks when a segment closes. It is checked against brute force.
  • Pressure: an EPANET 2.2 model of the whole network. It reproduces the 2020 Clinton Drive break, which dropped pressure citywide.
  • Customer-hours: for each scenario, $$\text{CH} = \sum_{p \in \text{phases}} c_p \, t_p,$$ where $c_p$ is customers affected in phase $p$ (pressure down $\ge 15$ psi while gushing; shut off or cut off once isolated) and $t_p$ its duration.
  • Break rates: 11,119 breaks a year (HPW FY2023), spread by pipe length and a per-diameter rate estimated from 3,495 real 311 calls. Each size class $d$ gets a credibility-weighted rate $$r_d = \frac{n_d + A\,r_0}{L_d + A}, \qquad A = \frac{25}{r_0},$$ so small mains break about 1.65× as often per km as the average and 42″+ mains about 0.55×.
  • Repair planner: the dead-valve cost of segment $s$ is $\lambda_s\,(\text{CH}^{\text{real}}_s - \text{CH}^{\text{paper}}_s)$. A greedy pass picks the valves whose repair recovers the most.
  • Compute: all 72,171 breaks were simulated, and the 24,531 breaks that need a full-city pressure solve were pre-solved on a 7-node Slurm cluster in about 15 minutes. That's why every click answers in under a second.
  • Tiger Data:
    • a simulated year of 11,058 breaks, replayed minute by minute in all three scenarios (1.58 M rows in a compressed hypertable, compressed to 5.5 MB);
    • the 311 break calls in a second hypertable;
    • continuous aggregates and time_bucket queries behind the charts;
    • the result cache.
  • Stack:
    • Python (NumPy, SciPy, WNTR/EPANET);
    • FastAPI on Vultr behind Caddy HTTPS;
    • React and MapLibre with PMTiles vector tiles;
    • street search from the City's centerlines (116,320 intersections) plus the US Census geocoder.
  • Proofs: core guarantees are machine-checked in Bend 2. For example, a dead valve can never make an outage smaller.

Challenges I ran into

  • Is this even the right data? The City's water GIS is a June 2023 snapshot. I audited every layer for provenance and found defects that changed the answer. Hydrant gate valves were being treated as cutting mains. 1,096 tees weren't connected to the pipes they touch.
  • The pressure model lied politely. My first metric, "newly below 20 psi", lit up the wrong side of town. The cause was a starved baseline in Kingwood, where every source had the same flow cap. I re-dispatched supply to where pressure fell short, and switched to pressure drop from normal.
  • Bugs that only a browser finds: clicking through the app revealed that a dead valve was shortening repair time in 2,784 breaks. I fixed the timeline logic and corrected every batch result exactly.
  • Scale: a full-city solve takes seconds. Interactive speed needed a local 4 km solve (median error 0.4 psi), a cluster-wide pre-solve, and a compact bitset encoding that cut the largest responses from 5 MB to 150 KB.
  • Validation: public outage counts for real breaks are rare. Only 2 news-reported breaks gave comparable numbers. I say so in the app rather than overclaim.

What I learned

  • Infrastructure data needs an audit before it needs a model. The defects I found mattered more than any modelling choice.
  • Separate what's robust from what's modelled. Shut-off time comes from network connectivity and the City's records. Gushing time comes from an uncalibrated pressure model. ValveRank labels which number comes from which.
  • Time-series databases fit "what happened when" questions well, including simulated ones. A year of minute-level outages compresses to a few megabytes and answers weekly questions instantly.

What's next

  • Calibrate the pressure model with City SCADA data.
  • Add work-order history, so repaired valves drop off the list.
  • Give Houston Public Works a ranked repair list it can schedule.

Built at CodeRED: Orion 2026 with Claude Code (AI coding assistant). Data: City of Houston public GIS, Houston Public Works, US Census Bureau, OpenStreetMap.

Built With

Share this project:

Updates

Submission history