A geospatial risk analysis dashboard that ranks 11 districts in Southern Punjab, Pakistan by composite risk scores. It combines data from multiple authoritative sources and uses the Analytic Hierarchy Process (AHP) to let decision-makers explore, weight, and visualize district-level risks in real time.
The dashboard synthesizes 7 risk criteria into a single composite score for each district:
| Criterion | Data Source |
|---|---|
| Blackout vulnerability (load shedding hours) | NEPRA |
| Flood exposure | NDMA (2022) |
| Heat stress (max temperature May–Sep) | Open-Meteo |
| 4G coverage gaps | PTA |
| Healthcare deficits (hospitals + clinics) | OpenStreetMap |
| Infrastructure gaps (substations + towers) | OpenStreetMap |
| Population exposure | PBS Census 2023 |
Users can adjust criterion weights via sliders or choose a preset scenario (Monsoon, Grid Crisis, Heat Wave, etc.), and the map instantly recolors to reflect the new priority ranking.
Multan · Khanewal · Rajanpur · Dera Ghazi Khan · Bahawalpur · Bahawalnagar · Lodhran · Pakpattan · Sahiwal · Okara · Rahim Yar Khan
- Interactive choropleth map — districts colored by risk tier (Critical / High / Moderate / Low)
- AHP weight sliders — adjust the importance of each criterion (1–10 scale) and see live percentage contributions
- 5 preset scenarios — Equal Weight, Monsoon, Grid Crisis, Heat Wave, Communications Blackout
- District detail card — click any district to see its score breakdown, raw indicators, and rank
- Risk summary bar — shows distribution of risk tiers and the top 3 highest-risk districts
- Export to JSON or CSV — download the current analysis with metadata and timestamps
- Scenario comparison — side-by-side comparison of multiple scenarios via the API
- WCAG 2.1 AA accessible — keyboard navigable, screen-reader friendly, sufficient color contrast
| Layer | Technology |
|---|---|
| Backend | Python 3 · Flask 3.0 · Flask-CORS |
| Frontend | React 18 · Vite 5 · Leaflet 1.9 |
| Maps | Leaflet.js with CartoDB dark basemap |
| Data | JSON files (no database required) |
| Styling | Custom CSS with CSS variables (dark theme) |
- Python 3.9+
- Node.js 18+
git clone https://github.com/Qandeel-01/Black-Sky-Sentinel.git
cd Black-Sky-Sentinel# Windows PowerShell
python -m venv backend\.venv
& backend\.venv\Scripts\Activate.ps1
pip install -r backend/requirements.txt
python backend/app.py# macOS / Linux
python3 -m venv backend/.venv
source backend/.venv/bin/activate
pip install -r backend/requirements.txt
python backend/app.pyThe Flask API runs at http://localhost:5000.
In a separate terminal:
cd frontend
npm install
npm run devThe app opens at http://localhost:5173. Vite proxies all /api requests to the Flask backend automatically.
start.batThis launches both the backend and frontend in separate console windows.
Copy the example environment files and edit as needed:
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.envBackend (backend/.env)
FLASK_ENV=development
FLASK_PORT=5000
CORS_ORIGINS=http://localhost:5173,http://localhost:3000
DATA_PATH=data
LOG_LEVEL=INFO
LOG_PATH=logsFrontend (frontend/.env)
VITE_API_BASE_URL=http://localhost:5000| Method | Endpoint | Description |
|---|---|---|
GET |
/health |
Server health check and list of all endpoints |
GET |
/api/real-scores |
Full district data with raw indicators and 0–100 scores |
GET |
/api/districts |
Compact district list with metadata |
GET |
/api/criteria |
Criterion definitions and data sources |
GET |
/api/scenarios |
Preset AHP scenario definitions |
GET |
/api/geojson |
GeoJSON boundaries for all 11 districts |
GET |
/api/settlements |
Settlement polygons (if generated) |
POST |
/api/calculate |
Compute composite scores from custom weights |
GET |
/api/report/<district_id> |
Detailed report for a single district |
POST |
/api/compare |
Side-by-side scenario comparison |
curl -X POST http://localhost:5000/api/calculate \
-H "Content-Type: application/json" \
-d '{"weights": {"blackout": 8, "flood": 6, "heat": 4, "coverage": 5, "healthcare": 7, "infrastructure": 5, "population": 6}}'black-sky-sentinel/
├── backend/
│ ├── app.py # Flask API (8 endpoints, AHP engine)
│ ├── requirements.txt
│ ├── .env.example
│ └── data/
│ ├── real_scores.json # District scores + raw indicators
│ ├── southern_punjab.geojson # Map boundaries
│ └── settlements.json # Settlement polygons
├── frontend/
│ └── src/
│ ├── App.jsx # Root component, state management, export
│ ├── components/
│ │ ├── Map.jsx # Leaflet choropleth map
│ │ ├── AHPPanel.jsx # Weight sliders + scenario buttons
│ │ ├── DistrictCard.jsx # District detail panel
│ │ ├── RiskSummaryBar.jsx # Top bar with tier counts
│ │ └── Legend.jsx # Risk tier color legend
│ └── App.css
├── dashboard.html # Standalone single-file version
├── start.bat # Windows launcher
└── README.md
| Source | What It Provides |
|---|---|
| NEPRA | Load shedding duration by district |
| NDMA | Flood exposure data (2022 floods) |
| PBS | Population by district (Census 2023) |
| PTA | 4G mobile network coverage |
| OpenStreetMap | Hospitals, clinics, substations, towers |
| Open-Meteo | Historical max temperatures |
- Live NEPRA load-shedding feed (replacing static estimates)
- Sentinel-1 SAR-based flood inundation overlay for real-time monsoon tracking
- District drill-down page with time-series charts per criterion
- PDF report export with scenario summary
MIT — see LICENSE for details.