Skip to content
 
 

Repository files navigation

Vāyu — India Pollution × Mortality Research Dashboard

A decade of air quality data across 31 Indian states, matched against disease mortality records — revealing how particulate pollution drives death at a measurable, statistically significant scale.


Overview

Vāyu is a full-stack research platform that combines historical air pollution data, real-time AQI monitoring, soil and water quality metrics, and ML-powered forecasting to visualize the relationship between environmental pollution and disease mortality across India (2013–2023).

The platform covers 200+ Indian cities and is built as a three-service architecture: a static frontend, a Node.js API backend, and a Python ML microservice.


Features

  • Live AQI Map — Real-time air quality index from the CPCB API, rendered on an interactive Leaflet map with city-level markers and color-coded AQI bands
  • Historical Trends — PM2.5, AQI, and pollutant trends from 2013–2023 across Indian states and cities
  • Pollution × Mortality Correlations — Statistical analysis linking particulate pollution to disease-specific death rates (GBD dataset)
  • ML Forecasting — Random Forest model predicting future PM2.5 levels using lag features and weather covariates
  • Multi-metric Toggle — Switch between Air Quality (AQI), Soil Pollution, Water Quality, and Noise Pollution layers
  • City Comparison Nodes — Drag-and-drop comparison of up to N cities side by side on the map
  • Research Dashboard — Curated findings, regression results, and phase-by-phase analysis output
  • Deaths Modal — Estimated mortality attributable to pollution per city/state

Architecture

┌─────────────────────────────────────────────────┐
│              Frontend (HTML/CSS/JS)              │
│  Leaflet · Chart.js · Vanilla JS modules         │
│  Deployed: Vercel                                │
└──────────────────┬──────────────────────────────┘
                   │ REST API calls
┌──────────────────▼──────────────────────────────┐
│           Backend (Node.js / Express)            │
│  Routes: /api/past · /api/present · /api/future  │
│          /api/water · /api/soil                  │
│  Deployed: Render                                │
└──────────────────┬──────────────────────────────┘
                   │ HTTP (port 5001)
┌──────────────────▼──────────────────────────────┐
│          ML Service (Python / Flask)             │
│  Random Forest · scikit-learn · StandardScaler   │
│  Deployed: Render                                │
└─────────────────────────────────────────────────┘

API Endpoints

Method Endpoint Description
GET /api/past/city/:city Historical AQI & pollutant data
GET /api/present/city/:city Live AQI from CPCB API
GET /api/future/city/:city ML-predicted AQI (next period)
GET /api/water Water quality data by station
GET /api/soil Soil pollution data by district
GET /api/health Backend health check

Tech Stack

Layer Technology
Frontend HTML5, CSS3, Vanilla JS (ES modules)
Maps Leaflet.js
Charts Chart.js 4
Backend Node.js ≥ 18, Express 4, node-fetch, dotenv
ML Service Python 3.11, Flask, scikit-learn 1.5.2, pandas, numpy
ML Model Random Forest Regressor + StandardScaler
Data CPCB API (live AQI), GBD dataset (mortality), custom CSVs
Containerization Docker + Docker Compose
Deployment Vercel (Frontend), Render (Backend + ML)

Project Structure

Pollution_Project-main/
├── FrontEnd/                  # Static frontend
│   ├── index.html             # Research dashboard & hero
│   ├── map.html               # Live AQI map
│   ├── research.html          # Detailed research findings
│   ├── js/
│   │   ├── app.js             # Entry point, map init, module boot
│   │   ├── aqi-engine.js      # AQI calculation logic
│   │   ├── charts.js          # Chart.js wrappers
│   │   ├── data-loader.js     # API fetch orchestration
│   │   ├── ml-section.js      # ML forecast UI
│   │   ├── node-manager.js    # City comparison nodes
│   │   ├── popups.js          # Map popup rendering
│   │   ├── search.js          # City search
│   │   ├── soil-loader.js     # Soil layer
│   │   ├── water-loader.js    # Water layer
│   │   └── deaths-modal.js    # Mortality modal
│   ├── styles/                # Modular CSS
│   ├── nginx.conf             # Nginx config for Docker
│   └── vercel.json            # Vercel routing config
│
├── Backend/                   # Node.js API
│   ├── server.js              # Express app entry point
│   ├── routes/
│   │   ├── analysis.js        # Past/present/future AQI routes
│   │   ├── water.js           # Water quality routes
│   │   └── soil.js            # Soil pollution routes
│   ├── data/                  # Pre-processed JSON data files
│   │   ├── city_data.json
│   │   ├── city_coords.json
│   │   ├── corr_data.json
│   │   ├── meta_data.json
│   │   ├── soil_data.json
│   │   └── water_quality.json
│   ├── package.json
│   └── Dockerfile
│
├── ml_model/                  # Python ML microservice
│   ├── ml_service.py          # Flask prediction server
│   ├── save_models.py         # Re-train & save model artifacts
│   ├── models/
│   │   ├── rf_model.pkl       # Trained Random Forest
│   │   └── scaler.pkl         # Fitted StandardScaler
│   ├── requirements.txt
│   └── Dockerfile
│
├── notebooks/                 # Jupyter analysis pipeline
│   ├── Phase0.ipynb           # Data ingestion & column classification
│   ├── Phase0.5.ipynb         # Data cleaning
│   ├── Phase1.ipynb           # Air pollution EDA
│   ├── phase_2_disease_clean.ipynb  # Disease mortality cleaning
│   ├── phase_3_join.ipynb     # Merging pollution + mortality
│   ├── phase_4_aqi.ipynb      # AQI computation
│   └── phase_5_ml.ipynb       # Model training & evaluation
│
├── outputs/                   # Pipeline output CSVs
│   ├── air_pollution_master.csv
│   ├── air_pollution_with_aqi.csv
│   ├── combined_master.csv
│   ├── disease_master.csv
│   ├── final_dataset/         # Per-city CSV files (200+ cities)
│   ├── phase5_model_summary.csv
│   └── taskb_correlation_results.csv
│
├── docker-compose.yml         # Local multi-service orchestration
├── render.yaml                # Render deployment config
├── env.example                # Environment variable template
└── DEPLOY.md                  # Full deployment guide

Data Pipeline

The research data was built through 6 phases of Jupyter notebook processing:

Phase Notebook Description
0 Phase0.ipynb Raw data ingestion, column classification
0.5 Phase0.5.ipynb Data cleaning, outlier removal
1 Phase1.ipynb Air pollution EDA, PM2.5 trend analysis
2 phase_2_disease_clean.ipynb GBD disease mortality cleaning
3 phase_3_join.ipynb Joining pollution + mortality datasets
4 phase_4_aqi.ipynb AQI index computation (CPCB methodology)
5 phase_5_ml.ipynb Random Forest training, evaluation, export

Machine Learning Model

The ML service exposes a /predict endpoint called by the Node backend for the /api/future/:city route.

Model: Random Forest Regressor
Target: PM2.5 concentration (next period)
Features: PM2.5 lag-1, PM2.5 lag-2, temperature, relative humidity, wind speed, rainfall
Preprocessing: StandardScaler (fitted on training set, serialized as scaler.pkl)

Note: rf_model.pkl and scaler.pkl are tied to scikit-learn 1.5.2. Do not upgrade scikit-learn without retraining and re-saving the models.

To retrain the model from scratch:

cd ml_model
python save_models.py

Local Development

You need three terminals running simultaneously.

Prerequisites

  • Node.js ≥ 18
  • Python ≥ 3.11
  • Git

Terminal 1 — ML Service

cd ml_model
pip install -r requirements.txt
python ml_service.py
# Starts on http://localhost:5001
# Health check: http://localhost:5001/health

Terminal 2 — Backend

cd Backend
npm install
cp ../env.example .env      # first time only — fill in your CPCB_API_KEY
node server.js
# Starts on http://localhost:5000
# Health check: http://localhost:5000/api/health

Terminal 3 — Frontend

cd FrontEnd

# Option A: VS Code Live Server (recommended — auto-reloads)
# Right-click index.html → "Open with Live Server"

# Option B: Python
python -m http.server 5500
# Open http://localhost:5500

The frontend reads from http://localhost:5000/api by default — no config changes needed.


Docker (Local)

To run all three services with Docker Compose:

# Copy and fill in environment variables
cp env.example .env

# Build and start all containers
docker compose up -d

# Check status
docker compose ps

# View logs
docker compose logs -f

# Stop everything
docker compose down

Services and their internal hostnames:

Container Hostname Port
vayu_ml_service ml_service 5001
vayu_backend backend 5000
vayu_frontend frontend 80

Environment Variables

Copy env.example to Backend/.env and fill in the values:

PORT=5000
NODE_ENV=production

# Internal URL of the ML service
ML_SERVICE_URL=http://ml_service:5001

# Allowed CORS origin for the frontend
FRONTEND_URL=http://localhost

# CPCB Air Quality API key from data.gov.in
# Get one at: https://data.gov.in/resource/real-time-air-quality-index-various-locations
CPCB_API_KEY=your_cpcb_api_key_here

Never commit your actual API key. Only put it in your local .env or as a secret environment variable in your hosting provider.


Production Deployment

The project is configured for Vercel (frontend) + Render (backend + ML). Follow the order below — services depend on each other's URLs.

Step 1: Push all files to GitHub.

Step 2: Deploy the ML service on Render first.
Render auto-detects render.yaml. Deploy vayu-ml-service and note the assigned URL (e.g., https://vayu-ml-service.onrender.com). Test: GET /health should return { "model_loaded": true }.

Step 3: Deploy the backend on Render.
Set these environment variables in the Render dashboard:

Variable Value
ML_SERVICE_URL URL from Step 2
FRONTEND_URL Your Vercel URL (set after Step 4)
CPCB_API_KEY Your key from data.gov.in

Step 4: Deploy the frontend on Vercel.
Connect your GitHub repo. Vercel reads FrontEnd/vercel.json automatically. Set the VAYU_API_BASE to your Render backend URL.

Full step-by-step instructions are in DEPLOY.md.


AQI Color Scale

AQI Range Category Color
0–50 Good 🟢 #a8e063
51–100 Satisfactory 🟡 #fdd835
101–200 Moderate 🟠 #ff7c00
201–300 Poor 🔴 #f50057
301–400 Very Poor 🟣 #9c27b0
401+ Severe #6a0080

Data Sources

  • Air Quality: Central Pollution Control Board (CPCB), India — data.gov.in
  • Disease Mortality: Global Burden of Disease (GBD) Study
  • Soil & Water: Processed from government monitoring datasets
  • City Coordinates: Custom curated city_coords.json

License

This project was built for research and educational purposes. See individual data source licenses for data usage terms.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages