sumit1703 Claude Opus 4.8 commited on
Commit
8661e65
·
1 Parent(s): d818eb1

feat: mark Delhi/NCR on maps; reframe to Delhi; polish README

Browse files

- visualizer: overlay Delhi star + NCR bounding box on full WRF-India domain
- app: enable mark_delhi, retitle subtitle/footer to Delhi/NCR (IIT-Delhi)
- README: restructured with badges, tables, run-local, PM2.5 guide

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Files changed (3) hide show
  1. README.md +100 -41
  2. app.py +5 -3
  3. visualizer.py +32 -0
README.md CHANGED
@@ -9,7 +9,7 @@ python_version: "3.12"
9
  app_file: app.py
10
  pinned: false
11
  license: mit
12
- short_description: PM2.5 forecast demo with saved predictions
13
  datasets:
14
  - sumit1703/pm25-forecasting-data
15
  tags:
@@ -17,72 +17,131 @@ tags:
17
  - air-quality
18
  - pm25
19
  - pollution-forecasting
 
20
  - deep-learning
21
  - data-visualization
22
  suggested_hardware: cpu-basic
23
  ---
24
 
25
- # 🌬️ PM2.5 Pollution Forecasting Demo
26
 
27
- **ANRF AISEHack Phase 2 — Theme 2 — Pollution Forecasting (IIT Delhi)**
28
 
29
- This demo visualizes predictions from a **ConvLSTM + Fourier Neural Operator (FNO)** hybrid model
30
- trained to forecast PM2.5 air pollution levels across a 140×124 spatial grid over Northern India.
31
 
32
- ## Live Links
33
 
34
- - Live Demo: https://huggingface.co/spaces/sumit1703/pm25-forecasting
35
- - Dataset: https://huggingface.co/datasets/sumit1703/pm25-forecasting-data
36
- - GitHub: https://github.com/sumitjadhav1703/pm25-forecasting-demo
 
37
 
38
- ## Important Note
39
 
40
- This Space visualizes precomputed PM2.5 predictions saved from the Kaggle GPU run. It does not run live model inference, training, or torch at runtime.
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
- ## How to Use
 
 
 
 
 
43
 
44
- 1. Use the **Test Window** slider to select a time period from the test dataset
45
- 2. Use the **Forecast Hour** slider to select how far ahead (+1h to +16h)
46
- 3. Compare the last known PM2.5 map (left) with the model's forecast (right)
47
- 4. Read the statistics below the maps
48
 
49
- ## Model Architecture
50
 
51
  | Component | Details |
52
  |-----------|---------|
53
- | Encoder | Stacked ConvLSTM (2 layers) |
54
- | Spatial | Fourier Neural Operator (FNO) |
55
- | Decoder | UNet with SE blocks |
56
- | Input | 10 hours × 20 atmospheric features × 140×124 grid |
57
- | Output | 16-hour PM2.5 forecast |
58
- | Training | Kaggle T4 GPU, ~8 hours |
 
 
59
 
60
- ## Competition Results
61
 
62
- - **Competition:** ANRF AISEHack Phase 2 — Theme 2 (IIT Delhi)
63
- - **Team:** Binary Bombers
64
- - **Phase 2 Rank:** 2
65
- - **Final Score:** 0.8795 (sMAPE-based)
 
 
66
 
67
- ## Kaggle Leaderboard Proof
 
68
 
69
- The final private leaderboard for **ANRF - AISEHack - Phase 2 - Theme 2 - Pollution Forecasting (IITD)** shows:
70
 
71
- * **Team:** Binary Bombers
72
- * **Final Rank:** 2
73
- * **Final Score:** 0.8795
74
- * **Entries:** 21
75
 
76
- > Note: Kaggle competition pages may require login to view the leaderboard.
 
 
 
77
 
78
  ![Kaggle Phase 2 Rank 2 Proof](assets/proof/kaggle-phase2-rank2.png)
79
 
80
- Competition link: https://www.kaggle.com/competitions/anrf-aise-hack-phase-2-theme-2-pollution-forecasting-iitd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
- ## Dataset
83
 
84
- The competition dataset contains 4 months of WRF-simulated atmospheric data:
85
- APRIL_16, JULY_16, OCT_16, DEC_16. Features include PM2.5, wind components,
86
- temperature, PBLH, and various emission tracers.
87
 
88
- > Built by Sumit — B.Tech AI & Data Science, JNEC MGM University
 
9
  app_file: app.py
10
  pinned: false
11
  license: mit
12
+ short_description: Delhi / NCR PM2.5 forecast demo with saved predictions
13
  datasets:
14
  - sumit1703/pm25-forecasting-data
15
  tags:
 
17
  - air-quality
18
  - pm25
19
  - pollution-forecasting
20
+ - delhi
21
  - deep-learning
22
  - data-visualization
23
  suggested_hardware: cpu-basic
24
  ---
25
 
26
+ <div align="center">
27
 
28
+ # 🌬️ PM2.5 Pollution Forecasting Delhi / NCR
29
 
30
+ **Deep-learning air-quality forecasting for Delhi and the National Capital Region**
 
31
 
32
+ _ANRF · AISEHack Phase 2 · Theme 2 — Pollution Forecasting · **IIT Delhi**_
33
 
34
+ [![Live Demo](https://img.shields.io/badge/🤗_Live_Demo-HF_Spaces-blue)](https://huggingface.co/spaces/sumit1703/pm25-forecasting)
35
+ [![Dataset](https://img.shields.io/badge/🤗_Dataset-pm25--forecasting--data-yellow)](https://huggingface.co/datasets/sumit1703/pm25-forecasting-data)
36
+ [![GitHub](https://img.shields.io/badge/GitHub-source-black?logo=github)](https://github.com/sumitjadhav1703/pm25-forecasting-demo)
37
+ [![Rank](https://img.shields.io/badge/Phase_2_Rank-🥈_2nd-silver)](https://www.kaggle.com/competitions/anrf-aise-hack-phase-2-theme-2-pollution-forecasting-iitd)
38
 
39
+ </div>
40
 
41
+ ---
42
+
43
+ ## Overview
44
+
45
+ A **ConvLSTM + Fourier Neural Operator (FNO)** hybrid model forecasts PM2.5 up to **16 hours ahead**.
46
+ Predictions run on a WRF simulation grid (140 × 124, ~25 km) covering India, with **Delhi and the
47
+ surrounding NCR highlighted** on every map — the focus region of the IIT-Delhi competition.
48
+
49
+ > **Note:** This Space visualizes precomputed predictions saved from the Kaggle GPU run.
50
+ > It does **not** run live model inference, training, or `torch` at runtime.
51
+
52
+ ---
53
+
54
+ ## 🖱️ How to Use
55
 
56
+ | Step | Action |
57
+ |------|--------|
58
+ | 1 | Drag the **Test Window** slider to pick a time period from the test set |
59
+ | 2 | Drag the **Forecast Hour** slider to choose how far ahead (+1h → +16h) |
60
+ | 3 | Compare the last-known map (left) with the model's forecast (right) — **Delhi / NCR is boxed and starred** |
61
+ | 4 | Read the forecast statistics below the maps |
62
 
63
+ ---
 
 
 
64
 
65
+ ## 🧠 Model Architecture
66
 
67
  | Component | Details |
68
  |-----------|---------|
69
+ | **Encoder** | Stacked ConvLSTM (2 layers) |
70
+ | **Spatial operator** | Fourier Neural Operator (FNO) |
71
+ | **Decoder** | UNet with SE blocks |
72
+ | **Input** | 10 hours × 20 atmospheric features × 140 × 124 grid |
73
+ | **Output** | 16-hour PM2.5 forecast |
74
+ | **Training** | Kaggle T4 GPU · ~8 hours |
75
+
76
+ ---
77
 
78
+ ## 🏆 Competition Results
79
 
80
+ | | |
81
+ |---|---|
82
+ | **Competition** | ANRF · AISEHack Phase 2 · Theme 2 — Pollution Forecasting (IIT Delhi) |
83
+ | **Team** | Binary Bombers |
84
+ | **Phase 2 Rank** | 🥈 **2** of 21 |
85
+ | **Final Score** | **0.8795** (sMAPE-based) |
86
 
87
+ <details>
88
+ <summary><strong>📊 Kaggle leaderboard proof</strong></summary>
89
 
90
+ <br>
91
 
92
+ Final private leaderboard for **ANRF AISEHack – Phase 2 – Theme 2 – Pollution Forecasting (IITD)**:
 
 
 
93
 
94
+ - **Team:** Binary Bombers
95
+ - **Final Rank:** 2
96
+ - **Final Score:** 0.8795
97
+ - **Entries:** 21
98
 
99
  ![Kaggle Phase 2 Rank 2 Proof](assets/proof/kaggle-phase2-rank2.png)
100
 
101
+ _Kaggle competition pages may require login to view the leaderboard._
102
+ [View competition →](https://www.kaggle.com/competitions/anrf-aise-hack-phase-2-theme-2-pollution-forecasting-iitd)
103
+
104
+ </details>
105
+
106
+ ---
107
+
108
+ ## 📦 Dataset
109
+
110
+ 4 months of WRF-simulated atmospheric data — **APRIL_16, JULY_16, OCT_16, DEC_16** —
111
+ covering the India domain with a focus on Delhi / NCR air quality. Features include
112
+ PM2.5, wind components, temperature, PBLH, and various emission tracers.
113
+
114
+ Hosted at 🤗 [`sumit1703/pm25-forecasting-data`](https://huggingface.co/datasets/sumit1703/pm25-forecasting-data).
115
+
116
+ ---
117
+
118
+ ## 🚀 Run Locally
119
+
120
+ ```bash
121
+ git clone https://github.com/sumitjadhav1703/pm25-forecasting-demo
122
+ cd pm25-forecasting-demo
123
+ pip install -r requirements.txt
124
+ python app.py # serves on http://0.0.0.0:7860
125
+ ```
126
+
127
+ Predictions download automatically from the HF dataset on first launch (cached to `/tmp`).
128
+
129
+ ---
130
+
131
+ ## 🗺️ PM2.5 Guide
132
+
133
+ | Range (μg/m³) | Level |
134
+ |---|---|
135
+ | 0 – 15 | 🟢 Good |
136
+ | 15 – 35 | 🟡 Moderate |
137
+ | 35 – 55 | 🟠 Sensitive |
138
+ | 55 – 150 | 🔴 Unhealthy |
139
+ | 150+ | 🟣 Hazardous |
140
+
141
+ ---
142
 
143
+ <div align="center">
144
 
145
+ Built by **Sumit** B.Tech AI &amp; Data Science, JNEC MGM University
 
 
146
 
147
+ </div>
app.py CHANGED
@@ -50,6 +50,7 @@ def update(window_slider: int, hour_slider: int):
50
  title=f"Input PM2.5 — Last Known Hour\n(Test window {original_window})",
51
  vmin=vmin, vmax=vmax,
52
  lat=LAT, lon=LON,
 
53
  )
54
 
55
  pred_img = make_heatmap(
@@ -57,6 +58,7 @@ def update(window_slider: int, hour_slider: int):
57
  title=f"Predicted PM2.5 — +{h + 1}h Forecast\n(Test window {original_window})",
58
  vmin=vmin, vmax=vmax,
59
  lat=LAT, lon=LON,
 
60
  )
61
 
62
  stats = compute_stats(pred_frame, input_frame)
@@ -71,8 +73,8 @@ with gr.Blocks(
71
  ) as demo:
72
 
73
  gr.Markdown("# 🌬️ PM2.5 Pollution Forecasting")
74
- gr.HTML('<p class="subtitle">ANRF AISEHack Phase 2 — Deep Learning Air Quality Forecast over India</p>')
75
- gr.Markdown("This demo visualizes precomputed predictions from saved `.npy` files. It does not run live model inference.")
76
 
77
  with gr.Row():
78
  with gr.Column(scale=1):
@@ -112,7 +114,7 @@ with gr.Blocks(
112
  ---
113
  **Model:** ConvLSTM encoder + Fourier Neural Operator (FNO) hybrid
114
  **Training:** Kaggle T4 GPU · ANRF competition dataset · 4 months × 16 atmospheric features
115
- **Grid:** 140 × 124 spatial points · Northern India
116
  **Input:** 10 hours of atmospheric data → **Output:** 16-hour PM2.5 forecast
117
  **Competition Rank:** 2 · Final Score: 0.8795 (sMAPE-based)
118
  """)
 
50
  title=f"Input PM2.5 — Last Known Hour\n(Test window {original_window})",
51
  vmin=vmin, vmax=vmax,
52
  lat=LAT, lon=LON,
53
+ mark_delhi=True,
54
  )
55
 
56
  pred_img = make_heatmap(
 
58
  title=f"Predicted PM2.5 — +{h + 1}h Forecast\n(Test window {original_window})",
59
  vmin=vmin, vmax=vmax,
60
  lat=LAT, lon=LON,
61
+ mark_delhi=True,
62
  )
63
 
64
  stats = compute_stats(pred_frame, input_frame)
 
73
  ) as demo:
74
 
75
  gr.Markdown("# 🌬️ PM2.5 Pollution Forecasting")
76
+ gr.HTML('<p class="subtitle">ANRF AISEHack Phase 2 (IIT Delhi) — Deep Learning PM2.5 Forecast · Delhi / NCR</p>')
77
+ gr.Markdown("This demo visualizes precomputed predictions from saved `.npy` files. It does not run live model inference. **Delhi and the surrounding NCR are marked on each map.**")
78
 
79
  with gr.Row():
80
  with gr.Column(scale=1):
 
114
  ---
115
  **Model:** ConvLSTM encoder + Fourier Neural Operator (FNO) hybrid
116
  **Training:** Kaggle T4 GPU · ANRF competition dataset · 4 months × 16 atmospheric features
117
+ **Grid:** 140 × 124 spatial points · WRF domain over India · **Delhi / NCR highlighted**
118
  **Input:** 10 hours of atmospheric data → **Output:** 16-hour PM2.5 forecast
119
  **Competition Rank:** 2 · Final Score: 0.8795 (sMAPE-based)
120
  """)
visualizer.py CHANGED
@@ -5,8 +5,14 @@ import matplotlib
5
  matplotlib.use("Agg") # non-interactive backend — required for server/Gradio
6
  import matplotlib.pyplot as plt
7
  import matplotlib.colors as mcolors
 
8
  from PIL import Image
9
 
 
 
 
 
 
10
  # WHO/AEQ PM2.5 breakpoints (μg/m³) for color bands annotation
11
  PM25_LEVELS = [
12
  (0, 15, "Good", "#00e400"),
@@ -26,6 +32,7 @@ def make_heatmap(
26
  lon: np.ndarray = None,
27
  figsize: tuple = (6, 5),
28
  dpi: int = 110,
 
29
  ) -> Image.Image:
30
  """
31
  Render a PM2.5 spatial heatmap.
@@ -83,6 +90,31 @@ def make_heatmap(
83
  for spine in ax.spines.values():
84
  spine.set_edgecolor("#444444")
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  ax.set_title(title, color="white", fontsize=9, pad=8, fontweight="bold")
87
 
88
  plt.tight_layout()
 
5
  matplotlib.use("Agg") # non-interactive backend — required for server/Gradio
6
  import matplotlib.pyplot as plt
7
  import matplotlib.colors as mcolors
8
+ from matplotlib.patches import Rectangle
9
  from PIL import Image
10
 
11
+ # Delhi / NCR reference geometry (used to annotate the full-domain map)
12
+ DELHI_LON, DELHI_LAT = 77.21, 28.61 # Delhi city centre
13
+ NCR_LON = (74.0, 80.0) # National Capital Region bounds
14
+ NCR_LAT = (26.0, 31.0)
15
+
16
  # WHO/AEQ PM2.5 breakpoints (μg/m³) for color bands annotation
17
  PM25_LEVELS = [
18
  (0, 15, "Good", "#00e400"),
 
32
  lon: np.ndarray = None,
33
  figsize: tuple = (6, 5),
34
  dpi: int = 110,
35
+ mark_delhi: bool = False,
36
  ) -> Image.Image:
37
  """
38
  Render a PM2.5 spatial heatmap.
 
90
  for spine in ax.spines.values():
91
  spine.set_edgecolor("#444444")
92
 
93
+ # Delhi / NCR annotation on the full geographic domain
94
+ if mark_delhi and lat is not None and lon is not None:
95
+ ax.add_patch(Rectangle(
96
+ (NCR_LON[0], NCR_LAT[0]),
97
+ NCR_LON[1] - NCR_LON[0],
98
+ NCR_LAT[1] - NCR_LAT[0],
99
+ fill=False, edgecolor="#00e5ff", linewidth=1.4,
100
+ linestyle="--", zorder=5,
101
+ ))
102
+ ax.plot(
103
+ DELHI_LON, DELHI_LAT,
104
+ marker="*", markersize=12,
105
+ markerfacecolor="#00e5ff", markeredgecolor="black",
106
+ markeredgewidth=0.6, zorder=6, label="Delhi (NCR)",
107
+ )
108
+ ax.annotate(
109
+ "Delhi",
110
+ xy=(DELHI_LON, DELHI_LAT),
111
+ xytext=(DELHI_LON + 1.6, DELHI_LAT + 1.4),
112
+ color="#00e5ff", fontsize=8, fontweight="bold", zorder=6,
113
+ )
114
+ leg = ax.legend(loc="lower left", fontsize=7, framealpha=0.35)
115
+ for txt in leg.get_texts():
116
+ txt.set_color("white")
117
+
118
  ax.set_title(title, color="white", fontsize=9, pad=8, fontweight="bold")
119
 
120
  plt.tight_layout()