Skip to content

hkevin01/charleston-flood-history-tracker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🌊 Charleston Flood History Tracker

30 years of NOAA-verified flood data for the Charleston, SC metro — interactive map, risk zones, and location decision analysis.

License GitHub Stars GitHub Forks Last Commit Repo Size Issues Python JavaScript OpenLayers Docker Data Source


Table of Contents


Overview

The Charleston Flood History Tracker is a static, browser-based geospatial application that visualises 314 unique flood-family events recorded by NOAA NCEI across the Charleston, SC metro between 1995 and 2024. Five study cities are covered — Charleston, North Charleston, Summerville, Goose Creek, and Hanahan — each within a 20-mile radius search perimeter.

The app also includes comparison-only benchmark cities in West Virginia (Fayetteville, Oak Hill, Bridgeport, Fairmont, and Clarksburg) to reinforce a key public-safety point: flooding is widespread across regions and is not limited to coastal South Carolina.

The application is aimed at residents making location and insurance decisions, journalists and researchers studying coastal flood risk, and public-health educators who need authoritative, citable data to communicate flood timing and frequency patterns.

Unlike forecast tools, this project answers the retrospective question: "How often, when, and where has flooding actually been documented here?"

Important

This is a historical analysis tool, not a real-time forecast system. Always follow active NWS warnings and local emergency instructions during a flood event.

(back to top ↑)


Key Features

Icon Feature Description Impact Status
🗺️ Interactive Map OpenLayers + OSM base map with flood event markers High ✅ Stable
🎨 Type-based Colours Flash Flood vs Flood events rendered in distinct colours Medium ✅ Stable
📏 Damage-scaled Symbols Marker radius scales with reported property damage High ✅ Stable
🟦 Risk-zone Polygons Per-city Gaussian heat surface classified into 5 risk levels High ✅ Stable
🔎 Live Filters Year range slider, event type toggle, minimum damage threshold High ✅ Stable
🏙️ City Comparison Panel Side-by-side event count and peak-month table for all 5 cities High ✅ Stable
🧭 Decision Analysis Section Safety, timing, insurance, and adaptation guidance per city Critical ✅ Stable
🐍 NOAA Data Pipeline Python script that ingests, filters, scores, and emits processed JSON Critical ✅ Stable
🐳 Docker Deployment Single-command containerised Nginx deployment Medium ✅ Stable
🧪 Test Suite Pytest unit tests for all data-pipeline helpers Medium ✅ Stable

Standout capabilities:

  • Gaussian risk-zone scoring weights log-scaled damage, injuries/fatalities, and coastal/surge event emphasis to produce a scientifically grounded 5-tier risk surface per city.
  • Decision-analysis section is content-driven, not generic — it answers the specific questions a person considering buying or renting in the metro would actually ask.
  • Zero external API calls at runtime — the app is fully static after the dataset build step, making it deployable anywhere (GitHub Pages, Nginx, Netlify, local file open).
  • $29.2 M in documented regional damage captured across included events, making the cost-of-flooding argument concrete.

(back to top ↑)


Dataset Headline Numbers

Metric Value
Study period 1995 – 2024 (30 years)
Unique flood events (deduped) 314
Cities covered 5
Search radius per city 20 miles
Reported regional damage $29,233,340
Flash Flood events 297 (94.6%)
Flood events 17 (5.4%)
Peak month (Aug) 86 events
Peak month (Oct) 61 events
Peak month (Jul) 58 events

Per-city event counts (1995–2024):

City Events in 20-mi Radius
Hanahan, SC 291
Goose Creek, SC 290
North Charleston, SC 284
Charleston, SC 255
Summerville, SC 206

Note

City counts overlap — a single NOAA event can fall within the 20-mile radius of multiple cities. The 314 figure is the deduplicated regional count.

(back to top ↑)


Architecture

flowchart TD
    subgraph Pipeline["🐍 Data Pipeline (Python)"]
        A[NOAA NCEI Bulk CSV Files<br/>1995–2024] --> B[build_dataset.py]
        B --> C{Filter: SC flood-family<br/>events in 20-mi radius}
        C --> D[Deduplicate by EVENT_ID]
        D --> E[Gaussian Risk-Zone Scoring<br/>per city grid]
        E --> F[charleston_floods_30y.json]
    end

    subgraph Frontend["🌐 Browser App (Vanilla JS)"]
        F --> G[app.js — data loader]
        G --> H[OpenLayers Map<br/>OSM base tiles]
        G --> I[Event Markers<br/>type colour + damage scale]
        G --> J[Risk-Zone Polygons<br/>5-tier heat surface]
        G --> K[Filter Controls<br/>year · type · damage]
        G --> L[City Comparison Panel]
        G --> M[Decision Analysis Section]
    end

    subgraph Deploy["🐳 Deployment"]
        H & I & J & K & L & M --> N[index.html]
        N --> O{Deployment target}
        O --> P[python -m http.server<br/>local dev]
        O --> Q[Docker + Nginx<br/>port 8091]
        O --> R[GitHub Pages / Netlify<br/>static host]
    end
Loading

Component responsibilities:

Component File Responsibility
Data pipeline scripts/build_dataset.py Download, filter, score, emit JSON
Map engine src/app.js Render map, events, risk zones, filters, panels
Stylesheet src/styles.css Responsive layout, legend, panel styles
Dataset data/processed/charleston_floods_30y.json Versioned output — committed to repo
Container docker/docker-compose.yml + Dockerfile Nginx static server on port 8091
Tests tests/test_build_dataset.py Pytest suite for pipeline helpers

The pipeline is completely decoupled from the frontend. The Python script runs once (or on demand) and writes a static JSON file that the browser reads directly — no server-side runtime, no database, no external API calls during page load.

(back to top ↑)


Data Flow

sequenceDiagram
    participant Dev as Developer
    participant Script as build_dataset.py
    participant NOAA as NOAA NCEI CSV
    participant JSON as processed JSON
    participant Browser as Browser / User

    Dev->>Script: python3 scripts/build_dataset.py
    Script->>NOAA: HTTP GET StormEvents_details_YYYY.csv (×30)
    NOAA-->>Script: CSV rows (all SC events)
    Script->>Script: Filter flood-family + 20-mi radius
    Script->>Script: Deduplicate by EVENT_ID
    Script->>Script: Gaussian risk scoring per city grid
    Script-->>JSON: Write charleston_floods_30y.json
    Dev->>Browser: Open index.html (or docker up)
    Browser->>JSON: fetch('./data/processed/charleston_floods_30y.json')
    JSON-->>Browser: 314 events + risk zones + metadata
    Browser->>Browser: Render OpenLayers map
    Browser->>Browser: Apply user filters (year / type / damage)
    Browser-->>Dev: Interactive flood history map
Loading

(back to top ↑)


Data & Metadata Provenance

This project intentionally separates primary event data from contextual metadata used to improve interpretation.

Primary event dataset (used directly in JSON)

Source What we use How it is used in this project Notes
NOAA NCEI Storm Events CSV bulk files StormEvents_details-ftp_v1.0_dYYYY_*.csv.gz Canonical source for event ID, time, county, lat/lon, event type, injuries/deaths, DAMAGE_PROPERTY, DAMAGE_CROPS, narratives Downloaded by scripts/build_dataset.py and written into data/processed/charleston_floods_30y.json

Contextual metadata sources (for interpretation and QA)

Source What we query Why it matters Integration status
NWS Charleston event archive Significant event summary pages and office archive references Confirms local meteorological context, rain totals, and event framing for known flood periods Referenced as supporting context
Iowa State IEM NWS text archive AFOS text products (LSR, FFW, etc.) for KCHS Provides time-stamped warning/report context not always visible in Storm Events CSV fields Referenced as supporting context
NWS text products (LSR/FFW) LSRCHS and FFWCHS examples for Aug 2005 Verified that North Charleston was under a Flash Flood Warning during the target event window Referenced as supporting context
SHELDUS (ASU/CEMHS) County-level hazard/loss catalogs Candidate secondary source for cross-checking loss totals when NOAA records are blank or sparse Research in progress

Provenance policy used in this repository

  1. Primary values in the shipped JSON come from NOAA Storm Events CSVs.
  2. When NOAA damage fields are blank but narratives describe physical impact, we flag the event as damageUnreported: true.
  3. External sources (NWS office pages, IEM product archives, newspapers, SHELDUS) are treated as corroborating metadata unless a defensible, traceable replacement value is established.
  4. No external estimate is silently substituted into NOAA numeric damage fields.

Known August 2005 finding (current status)

  • The Aug 24, 2005 Charleston-area flash flood event associated with Hawthorne Trailer Park / Rivers Avenue has narrative evidence of substantial impact, but NOAA DAMAGE_PROPERTY is blank in the source CSV.
  • Supporting metadata confirms contemporaneous flash flood warning context for North Charleston.
  • Current project behavior is to keep numeric damage at reported NOAA value and surface uncertainty with damageUnreported indicators.

(back to top ↑)


Event Distribution

pie title Charleston Metro — Flood Event Type Split (1995–2024)
    "Flash Flood" : 297
    "Flood" : 17
Loading
xychart-beta
    title "Monthly Flood Event Count — Charleston Metro (1995–2024)"
    x-axis ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
    y-axis "Events" 0 --> 100
    bar [14, 9, 12, 18, 22, 35, 58, 86, 45, 61, 21, 11]
Loading

Tip

The Aug–Oct window accounts for the single largest concentration of flood events, driven by Atlantic hurricane season and tropical moisture. Plan insurance renewals and preparedness reviews before August.

(back to top ↑)


Technology Stack

Technology Version Purpose Why Chosen Alternatives Considered
OpenLayers 10.8 Interactive web map Fully open-source, no API key, rich vector layer API Leaflet (fewer vector features), Mapbox (paid)
OpenStreetMap Base tile layer Free, no API key, global coverage Google Maps (paid), Esri (paid)
Python 3.10+ Data pipeline Pandas + requests ecosystem, rapid CSV wrangling Node.js (weaker data libs for geospatial)
Pandas latest CSV ingestion & filtering Vectorised operations on large yearly CSVs Polars (less ecosystem maturity)
NumPy / SciPy latest Gaussian risk-zone surface Native grid computation, ndimage smoothing Manual convolution (slower)
Vanilla JS (ES2022) Frontend logic Zero build tool, zero dependencies at runtime React (overkill for static app)
Nginx alpine Static file server Minimal image size, production-grade caching headers Apache (heavier), Python http.server (dev only)
Docker + Compose latest Containerised deployment Reproducible environment, one-command deploy Manual server config
Pytest latest Pipeline test suite Standard Python testing, fixtures, parametrize unittest (more verbose)

(back to top ↑)


Setup & Installation

Prerequisites

  • Python 3.10 or newer
  • pip (or pipenv / uv)
  • A modern browser (Chrome, Firefox, Edge, Safari)
  • Docker + Docker Compose (optional — for containerised deployment)

1 — Clone the repository

git clone https://github.com/hkevin01/charleston-flood-history-tracker.git
cd charleston-flood-history-tracker

2 — Install Python dependencies

pip install -r requirements.txt
📋 Core Python dependencies
Package Purpose
pandas CSV ingestion and tabular filtering
numpy Grid arithmetic for risk-zone scoring
scipy Gaussian smoothing (ndimage.gaussian_filter)
requests HTTP download of NOAA bulk CSVs
pytest Test suite runner

3 — Build the dataset

This step downloads ~30 annual NOAA CSV files into data/raw/ (gitignored) and emits data/processed/charleston_floods_30y.json.

python3 scripts/build_dataset.py

Expected output (abbreviated):

[2026-04-26 18:09:55] Downloading StormEvents_details_1995.csv ...
...
[2026-04-26 18:09:56] 314 unique events written → data/processed/charleston_floods_30y.json

Warning

The raw CSV downloads total ~200 MB. They are excluded from the repo via .gitignore. Do not commit files in data/raw/.

4 — Run locally

python3 -m http.server 8091

Then open: http://localhost:8091

Tip

Press Ctrl+C to stop the local server.

5 — Docker deployment

docker compose -f docker/docker-compose.yml up -d

Open http://localhost:8091. To stop:

docker compose -f docker/docker-compose.yml down

(back to top ↑)


Usage

Map controls

Control Action
Scroll / pinch Zoom in and out
Click + drag Pan the map
Click event marker Open popup with event details (type, date, damage, injuries)
Click risk-zone polygon Show zone classification and city

Filter panel

  • Year range slider — narrow events to a specific period (e.g. 2010–2020).
  • Event type toggle — show Flash Flood only, Flood only, or both.
  • Minimum damage threshold — filter out low-damage events to focus on significant floods.

City comparison panel

Shows event counts and peak months for all five study cities side by side — useful for comparing relative flood exposure when considering a move within the metro.

The panel also includes a separate Regional Benchmark (WV Comparison Cities) table. These benchmark cities are not mapped in the Charleston view; they are included as cross-region context only.

Decision analysis section

Scroll below the map for the structured guidance section covering:

  1. How often flooding happens (frequency by city)
  2. When flooding tends to happen (seasonal peaks)
  3. What to do — home vs car vs sheltering in place
  4. Core safety measures referenced against NWS guidance
  5. Insurance discussion — NFIP scope, homeowners/renters exclusions, auto comprehensive
  6. How residents adapt to persistent flood risk

(back to top ↑)


Core Capabilities

🟦 Risk-Zone Scoring

The pipeline generates a per-city Gaussian risk surface over a regular lat/lon grid. Each flood event contributes a weighted Gaussian kernel whose amplitude is determined by:

  • Log-scaled reported damage (DAMAGE_PROPERTY)
  • Injury and fatality impact (INJURIES_DIRECT, DEATHS_DIRECT)
  • Event-type emphasis — coastal and storm-surge categories receive a higher multiplier

The resulting continuous surface is classified into five tiers via quantile thresholds:

Zone Label Colour
1 Low 🟦 Light blue
2 Guarded 🟩 Green
3 Elevated 🟨 Yellow
4 High 🟧 Orange
5 Most Affected 🟥 Red

🔎 Spatial Filtering Logic

An event is associated with a city when its start OR end coordinate falls within the 20-mile (≈ 32 km) great-circle radius from the city centre. Events are then deduplicated regionally by NOAA EVENT_ID to prevent double-counting in aggregate statistics.

Note

Overlap is intentional at the per-city level — a single storm can produce flooding within 20 miles of multiple city centres simultaneously.

🧭 Decision Analysis Content

The decision-analysis section uses the NOAA event data as evidence but supplements it with:

  • NWS Flood Safety guidance for action recommendations
  • NFIP / FloodSmart guidance for insurance coverage explanations
  • NAIC Auto Insurance Database as the best available public proxy for auto comprehensive claim frequency (no flood-only, city-level auto payout open dataset exists)

Caution

Auto insurance flood payout data is presented as state-level context only. City-level flood-specific auto payout open data does not exist in public NAIC or FEMA releases. Do not treat NAIC metrics as city-specific figures.

(back to top ↑)


Project Roadmap

gantt
    title Charleston Flood Tracker — Development Roadmap
    dateFormat  YYYY-MM-DD
    section Phase 1 · Data Pipeline
        NOAA ingestion & filtering   :done,    p1a, 2026-01-01, 2026-02-01
        Risk-zone scoring            :done,    p1b, 2026-02-01, 2026-03-01
        JSON output & tests          :done,    p1c, 2026-03-01, 2026-03-15
    section Phase 2 · Map Experience
        OpenLayers map + markers     :done,    p2a, 2026-03-01, 2026-03-20
        Risk-zone polygons           :done,    p2b, 2026-03-15, 2026-04-01
        Filter controls              :done,    p2c, 2026-04-01, 2026-04-10
    section Phase 3 · Analysis & Delivery
        City comparison panel        :done,    p3a, 2026-04-10, 2026-04-18
        Decision-analysis section    :done,    p3b, 2026-04-15, 2026-04-22
        Docker + docs + tests        :done,    p3c, 2026-04-20, 2026-04-26
    section Phase 4 · Enhancements
      Historical storm-track overlay    :done,    p4a, 2026-05-01, 2026-06-01
      FEMA flood-zone layer integration :done,    p4b, 2026-05-15, 2026-06-15
      Exportable city risk report (PDF) :done,    p4c, 2026-06-01, 2026-07-01
      Mobile-optimised layout           :done,    p4d, 2026-06-15, 2026-07-15
      Data-quality audit filters        :done,    p4e, 2026-07-10, 2026-07-25
      Filtered event CSV export         :done,    p4f, 2026-07-25, 2026-08-20
Loading
Phase Goals Target Status
1 — Data Pipeline NOAA ingestion, filtering, risk scoring, JSON output 2026-03 ✅ Complete
2 — Map Experience OpenLayers map, markers, polygons, filters 2026-04 ✅ Complete
3 — Analysis & Delivery Decision analysis, Docker, tests, docs 2026-04-26 ✅ Complete
4 — Enhancements Storm tracks, FEMA zones, PDF report, mobile, data quality filters 2026-08 🟡 In Progress

(back to top ↑)


Development Status

Version Stability Test Coverage Known Limitations
v1.0.0 (current) ✅ Stable Unit tests for pipeline helpers No flood-only city-level auto payout data available publicly
v1.0.0 ✅ Stable Manual UI verification Per-event damage dollars are sometimes unreported in NOAA source rows
v1.0.0 ✅ Stable Docker smoke-tested On-map compact legend overlay control not yet implemented
mindmap
  root((Charleston Flood Tracker))
    Data
      NOAA NCEI CSVs
        30 annual files
        SC flood-family filter
      Spatial Logic
        20-mile radius
        EVENT_ID dedup
      Risk Scoring
        Gaussian surface
        5-tier classification
    Frontend
      OpenLayers Map
        Event markers
        Risk polygons
        Filter controls
      Panels
        City comparison
        Decision analysis
    Deployment
      Local dev
        python http.server
      Docker
        Nginx alpine
      Static host
        GitHub Pages
        Netlify
    Testing
      Pytest suite
        Pipeline helpers
        Filter logic
Loading

(back to top ↑)


Important Limitations

Warning

NOAA Storm Events is an observational record, not a complete census. Events are included when a National Weather Service office issues a warning or a damage report is submitted. Minor flooding that went unreported will not appear in the dataset.

Warning

No flood-only, city-level auto insurance payout open data exists. The NAIC Auto Insurance Database reports state-level comprehensive claim frequency. It is used in the decision-analysis section as a directional proxy only — not a Charleston-specific figure.

Note

The 20-mile radius produces intentional overlap. City-level event counts in the comparison panel will sum to more than the 314 deduplicated regional events. This is expected and documented.

Data Quality Flags

Some events display a data-quality flag called damageUnreported.

  • Plain meaning: the NOAA record shows $0 because the damage field was left blank, not because no damage happened.
  • Why you might see it: the narrative says things like roads flooded, cars underwater, or structures impacted, but no dollar estimate was entered in the original report.
  • How to read it: treat $0 as unknown / not reported for that event, not as confirmed zero loss.

(back to top ↑)


Contributing

Contributions are welcome — whether that's correcting data, improving the map UX, or adding a new analysis dimension.

Quick workflow:

  1. Fork the repo
  2. Create a branch: git checkout -b feat/your-feature
  3. Make changes and run tests: pytest tests/
  4. Open a Pull Request using the PR template
📋 Detailed contributing guidelines

Code style

  • Python: PEP 8. black formatter accepted.
  • JavaScript: Match the existing style in src/app.js — no build tools, no bundlers.

Testing requirements

  • All pipeline helper functions must have a corresponding Pytest test in tests/test_build_dataset.py.
  • UI changes should be verified in at least Chrome and Firefox before submitting.

Data contributions

If you have a source that contradicts or supplements the current dataset, open a Data issue with a link to the authoritative source (NOAA NCEI, NWS, FEMA).

What NOT to commit

  • data/raw/ — raw NOAA CSV downloads are gitignored and must stay that way.
  • Any file containing API keys or credentials.

Issue templates

Template Use for
Bug report Something isn't working
Feature request New capability or enhancement
Data issue Incorrect, missing, or outdated flood data

Please read the Code of Conduct before contributing.

(back to top ↑)


License & Acknowledgements

License

This project is released under the MIT License — you are free to use, copy, modify, and distribute it with attribution. See LICENSE for the full text.

Data sources

Source Description Link
NOAA NCEI Storm Events Primary flood event records (1995–2024) CSV directory
NWS Charleston Event Archive Local event summary and historical office context weather.gov/chs/events
Iowa State IEM NWS Text Archive Historical AFOS text products (LSR/FFW/AFD/etc.) mesonet.agron.iastate.edu
NWS Flood Safety Action guidance referenced in decision-analysis section weather.gov
NFIP / FloodSmart Insurance guidance floodsmart.gov
NAIC Auto Insurance DB State-level auto comprehensive claim frequency proxy naic.org
SHELDUS (ASU/CEMHS) County-level hazard/loss cross-reference source cemhs.asu.edu/sheldus
OpenStreetMap Base map tiles openstreetmap.org

Inspiration

Structural approach inspired by a companion Tornado History Tracker project for the same Charleston metro study area.

Safety disclaimer

This project is a historical analysis and planning-support tool. It is not a forecast system and must not be used as a substitute for official NWS warnings, local emergency instructions, or professional insurance advice during an active flood event.

(back to top ↑)

About

30 years of NOAA-verified flood data for the Charleston, SC metro — interactive map, risk zones, and location decision analysis.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors