Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files
app.py
CHANGED
|
@@ -77,6 +77,98 @@ POLICY_EVENTS = {
|
|
| 77 |
{"year": 2012, "text": "Carbon farming legislation", "url": "https://en.wikipedia.org/wiki/Climate_change_in_Australia"},
|
| 78 |
{"year": 2022, "text": "Nature Repair Market Act", "url": "https://en.wikipedia.org/wiki/Climate_change_in_Australia"},
|
| 79 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
}
|
| 81 |
|
| 82 |
|
|
@@ -192,6 +284,7 @@ def get_forest_data(country: str) -> dict:
|
|
| 192 |
forest = _fetch_wb(code, "AG.LND.FRST.ZS")
|
| 193 |
governance = _fetch_wb(code, "RL.EST")
|
| 194 |
policies = POLICY_EVENTS.get(country, [])
|
|
|
|
| 195 |
|
| 196 |
summary = {}
|
| 197 |
if forest:
|
|
@@ -212,6 +305,7 @@ def get_forest_data(country: str) -> dict:
|
|
| 212 |
"forest": forest,
|
| 213 |
"governance": governance,
|
| 214 |
"policies": policies,
|
|
|
|
| 215 |
"summary": summary,
|
| 216 |
}
|
| 217 |
|
|
@@ -238,6 +332,8 @@ def explain_spike(country: str, year: int) -> dict:
|
|
| 238 |
|
| 239 |
policies = POLICY_EVENTS.get(country, [])
|
| 240 |
nearby_policies = [p for p in policies if abs(p["year"] - year) <= 3]
|
|
|
|
|
|
|
| 241 |
|
| 242 |
window = [f for f in forest if abs(f["year"] - year) <= 5]
|
| 243 |
window.sort(key=lambda x: x["year"])
|
|
@@ -288,6 +384,7 @@ def explain_spike(country: str, year: int) -> dict:
|
|
| 288 |
"rate_5yr_before": rate_before,
|
| 289 |
"rate_5yr_after": rate_after,
|
| 290 |
"nearby_policies": nearby_policies,
|
|
|
|
| 291 |
"context": context,
|
| 292 |
"window": window,
|
| 293 |
}
|
|
@@ -1143,9 +1240,14 @@ button.action:active {{
|
|
| 1143 |
<canvas id="chart"></canvas>
|
| 1144 |
</div>
|
| 1145 |
<div class="figure-caption">
|
| 1146 |
-
<span class="smallcaps">
|
| 1147 |
-
|
| 1148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1149 |
</div>
|
| 1150 |
</section>
|
| 1151 |
|
|
@@ -1377,14 +1479,14 @@ function renderChart(data, compareData) {{
|
|
| 1377 |
|
| 1378 |
const annotations = {{}};
|
| 1379 |
(data.policies || []).forEach((p, i) => {{
|
| 1380 |
-
annotations['
|
| 1381 |
type: 'line',
|
| 1382 |
xMin: p.year, xMax: p.year,
|
| 1383 |
-
borderColor: 'rgba(139, 42, 31, 0.
|
| 1384 |
borderWidth: 1,
|
| 1385 |
borderDash: [3, 4],
|
| 1386 |
}};
|
| 1387 |
-
annotations['
|
| 1388 |
type: 'point',
|
| 1389 |
xValue: p.year,
|
| 1390 |
yValue: data.forest.find(f => f.year === p.year)?.value || data.forest[0].value,
|
|
@@ -1395,6 +1497,26 @@ function renderChart(data, compareData) {{
|
|
| 1395 |
hoverRadius: 8,
|
| 1396 |
}};
|
| 1397 |
}});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1398 |
|
| 1399 |
chart = new Chart(ctx, {{
|
| 1400 |
type: 'line',
|
|
@@ -1442,8 +1564,12 @@ function renderChart(data, compareData) {{
|
|
| 1442 |
afterBody: function(items) {{
|
| 1443 |
if (!items.length) return;
|
| 1444 |
const year = Math.round(items[0].parsed.x);
|
|
|
|
| 1445 |
const policy = (data.policies || []).find(p => p.year === year);
|
| 1446 |
-
|
|
|
|
|
|
|
|
|
|
| 1447 |
}}
|
| 1448 |
}}
|
| 1449 |
}}
|
|
@@ -1637,7 +1763,7 @@ async function handlePointClick(year) {{
|
|
| 1637 |
|
| 1638 |
if (result.nearby_policies && result.nearby_policies.length) {{
|
| 1639 |
html += `<div class="nearby-block">
|
| 1640 |
-
<div class="k">Nearby policy events · ±3 years</div>`;
|
| 1641 |
result.nearby_policies.forEach(p => {{
|
| 1642 |
const pLink = p.url ? ` <a href="${{p.url}}" target="_blank" style="color:var(--ink-mute);font-size:11px">↗</a>` : '';
|
| 1643 |
html += `<div class="nearby-item"><span class="yr">${{p.year}}</span><span>${{p.text}}${{pLink}}</span></div>`;
|
|
@@ -1645,6 +1771,16 @@ async function handlePointClick(year) {{
|
|
| 1645 |
html += `</div>`;
|
| 1646 |
}}
|
| 1647 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1648 |
contentEl.innerHTML = html;
|
| 1649 |
}}
|
| 1650 |
|
|
|
|
| 77 |
{"year": 2012, "text": "Carbon farming legislation", "url": "https://en.wikipedia.org/wiki/Climate_change_in_Australia"},
|
| 78 |
{"year": 2022, "text": "Nature Repair Market Act", "url": "https://en.wikipedia.org/wiki/Climate_change_in_Australia"},
|
| 79 |
],
|
| 80 |
+
"United States": [
|
| 81 |
+
{"year": 2001, "text": "Healthy Forests Initiative", "url": "https://en.wikipedia.org/wiki/Healthy_Forests_Initiative"},
|
| 82 |
+
{"year": 2008, "text": "Lacey Act amended to ban illegal timber", "url": "https://en.wikipedia.org/wiki/Lacey_Act_of_1900"},
|
| 83 |
+
{"year": 2022, "text": "Inflation Reduction Act — $5B for forests", "url": "https://en.wikipedia.org/wiki/Inflation_Reduction_Act"},
|
| 84 |
+
],
|
| 85 |
+
"Russia": [
|
| 86 |
+
{"year": 1997, "text": "First Russian Forest Code", "url": "https://en.wikipedia.org/wiki/Forestry_in_Russia"},
|
| 87 |
+
{"year": 2006, "text": "New Forest Code — privatisation of management", "url": "https://en.wikipedia.org/wiki/Forestry_in_Russia"},
|
| 88 |
+
{"year": 2020, "text": "Forest protection reform after record fires", "url": "https://en.wikipedia.org/wiki/Forestry_in_Russia"},
|
| 89 |
+
],
|
| 90 |
+
"Bolivia": [
|
| 91 |
+
{"year": 1996, "text": "Forestry Law 1700 enacted", "url": "https://en.wikipedia.org/wiki/Deforestation"},
|
| 92 |
+
{"year": 2012, "text": "Mother Earth Law", "url": "https://en.wikipedia.org/wiki/Law_of_the_Rights_of_Mother_Earth"},
|
| 93 |
+
],
|
| 94 |
+
"Peru": [
|
| 95 |
+
{"year": 2011, "text": "Forest and Wildlife Law 29763", "url": "https://en.wikipedia.org/wiki/Deforestation_in_Peru"},
|
| 96 |
+
{"year": 2014, "text": "Joint Declaration with Norway & Germany", "url": "https://en.wikipedia.org/wiki/Deforestation_in_Peru"},
|
| 97 |
+
],
|
| 98 |
+
"Paraguay": [
|
| 99 |
+
{"year": 2004, "text": "Zero Deforestation Law (East region)", "url": "https://en.wikipedia.org/wiki/Deforestation"},
|
| 100 |
+
],
|
| 101 |
+
"Madagascar": [
|
| 102 |
+
{"year": 2003, "text": "Durban Vision — triple protected areas", "url": "https://en.wikipedia.org/wiki/Environment_of_Madagascar"},
|
| 103 |
+
{"year": 2015, "text": "National REDD+ strategy", "url": "https://en.wikipedia.org/wiki/REDD_and_REDD%2B"},
|
| 104 |
+
],
|
| 105 |
+
"Cameroon": [
|
| 106 |
+
{"year": 1994, "text": "Forest Law 94/01 enacted", "url": "https://en.wikipedia.org/wiki/Forestry_in_Cameroon"},
|
| 107 |
+
{"year": 2010, "text": "CAFI partnership initiated", "url": "https://en.wikipedia.org/wiki/Forestry_in_Cameroon"},
|
| 108 |
+
],
|
| 109 |
+
"Nigeria": [
|
| 110 |
+
{"year": 1999, "text": "Federal Forestry Policy", "url": "https://en.wikipedia.org/wiki/Forestry_in_Nigeria"},
|
| 111 |
+
{"year": 2017, "text": "Great Green Wall commitment", "url": "https://en.wikipedia.org/wiki/Great_Green_Wall_(Africa)"},
|
| 112 |
+
],
|
| 113 |
+
"Myanmar": [
|
| 114 |
+
{"year": 1992, "text": "Forest Law passed", "url": "https://en.wikipedia.org/wiki/Deforestation"},
|
| 115 |
+
{"year": 2014, "text": "Raw log export ban", "url": "https://en.wikipedia.org/wiki/Deforestation"},
|
| 116 |
+
],
|
| 117 |
+
"Tanzania": [
|
| 118 |
+
{"year": 2002, "text": "Forest Act enacted", "url": "https://en.wikipedia.org/wiki/Environmental_issues_in_Tanzania"},
|
| 119 |
+
{"year": 2015, "text": "National REDD+ strategy", "url": "https://en.wikipedia.org/wiki/REDD_and_REDD%2B"},
|
| 120 |
+
],
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
CLIMATE_EVENTS = {
|
| 125 |
+
"Australia": [
|
| 126 |
+
{"year": 2002, "text": "Millennium Drought intensifies", "url": "https://en.wikipedia.org/wiki/2000s_Australian_drought"},
|
| 127 |
+
{"year": 2009, "text": "Black Saturday bushfires (430k ha)", "url": "https://en.wikipedia.org/wiki/Black_Saturday_bushfires"},
|
| 128 |
+
{"year": 2020, "text": "Black Summer fires (18.6M ha)", "url": "https://en.wikipedia.org/wiki/2019%E2%80%9320_Australian_bushfire_season"},
|
| 129 |
+
],
|
| 130 |
+
"Indonesia": [
|
| 131 |
+
{"year": 1997, "text": "Southeast Asian haze from peat fires", "url": "https://en.wikipedia.org/wiki/1997_Southeast_Asian_haze"},
|
| 132 |
+
{"year": 2015, "text": "Peat fires burn 2.6M ha", "url": "https://en.wikipedia.org/wiki/2015_Southeast_Asian_haze"},
|
| 133 |
+
{"year": 2019, "text": "Major fire season, 1.6M ha burned", "url": "https://en.wikipedia.org/wiki/2019_Southeast_Asian_haze"},
|
| 134 |
+
],
|
| 135 |
+
"Brazil": [
|
| 136 |
+
{"year": 2019, "text": "Amazon fires spike 84%", "url": "https://en.wikipedia.org/wiki/2019_Amazon_rainforest_wildfires"},
|
| 137 |
+
{"year": 2020, "text": "Pantanal wetland fires (4M ha)", "url": "https://en.wikipedia.org/wiki/2020_Pantanal_wildfires"},
|
| 138 |
+
],
|
| 139 |
+
"Canada": [
|
| 140 |
+
{"year": 2005, "text": "Mountain pine beetle peak (18M ha)", "url": "https://en.wikipedia.org/wiki/Mountain_pine_beetle"},
|
| 141 |
+
{"year": 2016, "text": "Fort McMurray fire", "url": "https://en.wikipedia.org/wiki/2016_Fort_McMurray_wildfire"},
|
| 142 |
+
{"year": 2023, "text": "Record fire season (18.5M ha)", "url": "https://en.wikipedia.org/wiki/2023_Canadian_wildfires"},
|
| 143 |
+
],
|
| 144 |
+
"Russia": [
|
| 145 |
+
{"year": 2010, "text": "Moscow smog — wildfires kill 56k", "url": "https://en.wikipedia.org/wiki/2010_Russian_wildfires"},
|
| 146 |
+
{"year": 2019, "text": "Siberian fires (4M ha)", "url": "https://en.wikipedia.org/wiki/2019_Siberia_wildfires"},
|
| 147 |
+
{"year": 2021, "text": "Record Siberian fires (18.8M ha)", "url": "https://en.wikipedia.org/wiki/2021_Russia_wildfires"},
|
| 148 |
+
],
|
| 149 |
+
"China": [
|
| 150 |
+
{"year": 1998, "text": "Yangtze floods kill 4,000+", "url": "https://en.wikipedia.org/wiki/1998_China_floods"},
|
| 151 |
+
],
|
| 152 |
+
"United States": [
|
| 153 |
+
{"year": 2018, "text": "Camp Fire destroys Paradise", "url": "https://en.wikipedia.org/wiki/Camp_Fire_(2018)"},
|
| 154 |
+
{"year": 2020, "text": "Record fire season (4.2M acres)", "url": "https://en.wikipedia.org/wiki/2020_California_wildfires"},
|
| 155 |
+
{"year": 2023, "text": "Maui fires & Canadian smoke crisis", "url": "https://en.wikipedia.org/wiki/2023_Hawaii_wildfires"},
|
| 156 |
+
],
|
| 157 |
+
"Colombia": [
|
| 158 |
+
{"year": 2017, "text": "Deforestation spikes in post-FARC areas", "url": "https://en.wikipedia.org/wiki/Deforestation_in_Colombia"},
|
| 159 |
+
],
|
| 160 |
+
"Mexico": [
|
| 161 |
+
{"year": 2011, "text": "Worst drought in 70 years", "url": "https://en.wikipedia.org/wiki/Climate_change_in_Mexico"},
|
| 162 |
+
],
|
| 163 |
+
"Bolivia": [
|
| 164 |
+
{"year": 2019, "text": "Chiquitano fires burn 2.3M ha", "url": "https://en.wikipedia.org/wiki/2019_Amazon_rainforest_wildfires"},
|
| 165 |
+
],
|
| 166 |
+
"Madagascar": [
|
| 167 |
+
{"year": 2020, "text": "Severe drought in southern regions", "url": "https://en.wikipedia.org/wiki/Environment_of_Madagascar"},
|
| 168 |
+
],
|
| 169 |
+
"DR Congo": [
|
| 170 |
+
{"year": 2003, "text": "Second Congo War ends", "url": "https://en.wikipedia.org/wiki/Second_Congo_War"},
|
| 171 |
+
],
|
| 172 |
}
|
| 173 |
|
| 174 |
|
|
|
|
| 284 |
forest = _fetch_wb(code, "AG.LND.FRST.ZS")
|
| 285 |
governance = _fetch_wb(code, "RL.EST")
|
| 286 |
policies = POLICY_EVENTS.get(country, [])
|
| 287 |
+
climate = CLIMATE_EVENTS.get(country, [])
|
| 288 |
|
| 289 |
summary = {}
|
| 290 |
if forest:
|
|
|
|
| 305 |
"forest": forest,
|
| 306 |
"governance": governance,
|
| 307 |
"policies": policies,
|
| 308 |
+
"climate": climate,
|
| 309 |
"summary": summary,
|
| 310 |
}
|
| 311 |
|
|
|
|
| 332 |
|
| 333 |
policies = POLICY_EVENTS.get(country, [])
|
| 334 |
nearby_policies = [p for p in policies if abs(p["year"] - year) <= 3]
|
| 335 |
+
climate = CLIMATE_EVENTS.get(country, [])
|
| 336 |
+
nearby_climate = [c for c in climate if abs(c["year"] - year) <= 3]
|
| 337 |
|
| 338 |
window = [f for f in forest if abs(f["year"] - year) <= 5]
|
| 339 |
window.sort(key=lambda x: x["year"])
|
|
|
|
| 384 |
"rate_5yr_before": rate_before,
|
| 385 |
"rate_5yr_after": rate_after,
|
| 386 |
"nearby_policies": nearby_policies,
|
| 387 |
+
"nearby_climate": nearby_climate,
|
| 388 |
"context": context,
|
| 389 |
"window": window,
|
| 390 |
}
|
|
|
|
| 1240 |
<canvas id="chart"></canvas>
|
| 1241 |
</div>
|
| 1242 |
<div class="figure-caption">
|
| 1243 |
+
<span class="smallcaps">Legend —</span>
|
| 1244 |
+
<span style="display:inline-block;width:9px;height:9px;border-radius:50%;background:var(--oxblood);vertical-align:middle;margin-right:4px"></span> policy event
|
| 1245 |
+
·
|
| 1246 |
+
<span style="display:inline-block;width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:10px solid var(--amber);vertical-align:middle;margin-right:4px"></span> climate / disaster event
|
| 1247 |
+
·
|
| 1248 |
+
<span style="display:inline-block;width:12px;height:2px;background:var(--amber);vertical-align:middle;margin-right:4px"></span> rule of law
|
| 1249 |
+
<br>
|
| 1250 |
+
Hover the line to read an event. Click any year for a full dossier.
|
| 1251 |
</div>
|
| 1252 |
</section>
|
| 1253 |
|
|
|
|
| 1479 |
|
| 1480 |
const annotations = {{}};
|
| 1481 |
(data.policies || []).forEach((p, i) => {{
|
| 1482 |
+
annotations['pline' + i] = {{
|
| 1483 |
type: 'line',
|
| 1484 |
xMin: p.year, xMax: p.year,
|
| 1485 |
+
borderColor: 'rgba(139, 42, 31, 0.22)',
|
| 1486 |
borderWidth: 1,
|
| 1487 |
borderDash: [3, 4],
|
| 1488 |
}};
|
| 1489 |
+
annotations['ppoint' + i] = {{
|
| 1490 |
type: 'point',
|
| 1491 |
xValue: p.year,
|
| 1492 |
yValue: data.forest.find(f => f.year === p.year)?.value || data.forest[0].value,
|
|
|
|
| 1497 |
hoverRadius: 8,
|
| 1498 |
}};
|
| 1499 |
}});
|
| 1500 |
+
(data.climate || []).forEach((c, i) => {{
|
| 1501 |
+
annotations['cline' + i] = {{
|
| 1502 |
+
type: 'line',
|
| 1503 |
+
xMin: c.year, xMax: c.year,
|
| 1504 |
+
borderColor: 'rgba(168, 115, 42, 0.22)',
|
| 1505 |
+
borderWidth: 1,
|
| 1506 |
+
borderDash: [1, 3],
|
| 1507 |
+
}};
|
| 1508 |
+
annotations['cpoint' + i] = {{
|
| 1509 |
+
type: 'point',
|
| 1510 |
+
xValue: c.year,
|
| 1511 |
+
yValue: data.forest.find(f => f.year === c.year)?.value || data.forest[0].value,
|
| 1512 |
+
radius: 6,
|
| 1513 |
+
pointStyle: 'triangle',
|
| 1514 |
+
backgroundColor: AMBER,
|
| 1515 |
+
borderColor: PAPER_TINT,
|
| 1516 |
+
borderWidth: 2,
|
| 1517 |
+
hoverRadius: 9,
|
| 1518 |
+
}};
|
| 1519 |
+
}});
|
| 1520 |
|
| 1521 |
chart = new Chart(ctx, {{
|
| 1522 |
type: 'line',
|
|
|
|
| 1564 |
afterBody: function(items) {{
|
| 1565 |
if (!items.length) return;
|
| 1566 |
const year = Math.round(items[0].parsed.x);
|
| 1567 |
+
const lines = [];
|
| 1568 |
const policy = (data.policies || []).find(p => p.year === year);
|
| 1569 |
+
const climateEv = (data.climate || []).find(c => c.year === year);
|
| 1570 |
+
if (policy) lines.push('', '§ Policy — ' + policy.text);
|
| 1571 |
+
if (climateEv) lines.push('', '△ Climate — ' + climateEv.text);
|
| 1572 |
+
return lines;
|
| 1573 |
}}
|
| 1574 |
}}
|
| 1575 |
}}
|
|
|
|
| 1763 |
|
| 1764 |
if (result.nearby_policies && result.nearby_policies.length) {{
|
| 1765 |
html += `<div class="nearby-block">
|
| 1766 |
+
<div class="k">§ Nearby policy events · ±3 years</div>`;
|
| 1767 |
result.nearby_policies.forEach(p => {{
|
| 1768 |
const pLink = p.url ? ` <a href="${{p.url}}" target="_blank" style="color:var(--ink-mute);font-size:11px">↗</a>` : '';
|
| 1769 |
html += `<div class="nearby-item"><span class="yr">${{p.year}}</span><span>${{p.text}}${{pLink}}</span></div>`;
|
|
|
|
| 1771 |
html += `</div>`;
|
| 1772 |
}}
|
| 1773 |
|
| 1774 |
+
if (result.nearby_climate && result.nearby_climate.length) {{
|
| 1775 |
+
html += `<div class="nearby-block">
|
| 1776 |
+
<div class="k" style="color:var(--amber-deep)">△ Nearby climate events · ±3 years</div>`;
|
| 1777 |
+
result.nearby_climate.forEach(c => {{
|
| 1778 |
+
const cLink = c.url ? ` <a href="${{c.url}}" target="_blank" style="color:var(--ink-mute);font-size:11px">↗</a>` : '';
|
| 1779 |
+
html += `<div class="nearby-item"><span class="yr" style="color:var(--amber-deep)">${{c.year}}</span><span>${{c.text}}${{cLink}}</span></div>`;
|
| 1780 |
+
}});
|
| 1781 |
+
html += `</div>`;
|
| 1782 |
+
}}
|
| 1783 |
+
|
| 1784 |
contentEl.innerHTML = html;
|
| 1785 |
}}
|
| 1786 |
|