ElifSB's picture
Upload 6 files
10f00ac verified
Raw
History Blame Contribute Delete
23.1 kB
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime
import requests
from bs4 import BeautifulSoup
from fpdf import FPDF
import base64
def create_pdf_report(country, sector, forecast, gap, status, news_list):
pdf = FPDF()
pdf.add_page()
pdf.set_font("helvetica", "B", 16)
# Başlık
pdf.cell(0, 10, text="ClimateVision 2030 - Strategic Report", new_x="LMARGIN", new_y="NEXT", align="C")
# Mevcut veriler (Executive Summary & Compliance)
pdf.set_font("helvetica", "B", 14)
pdf.cell(0, 10, text="1. Executive Summary", new_x="LMARGIN", new_y="NEXT")
pdf.set_font("helvetica", "", 12)
pdf.multi_cell(0, 8, text=f"Country: {country} | Sector: {sector}\nForecast: {forecast} MtCO2e", new_x="LMARGIN", new_y="NEXT")
pdf.set_font("helvetica", "B", 14)
pdf.cell(0, 10, text="2. Compliance Audit", new_x="LMARGIN", new_y="NEXT")
pdf.set_font("helvetica", "", 12)
pdf.cell(0, 8, text=f"Status: {status}", new_x="LMARGIN", new_y="NEXT")
pdf.cell(0, 8, text=f"Mitigation Gap: {gap} MtCO2e", new_x="LMARGIN", new_y="NEXT")
# --- Section 3: Strategic Insights ---
pdf.ln(5)
pdf.set_font("helvetica", "B", 14)
pdf.cell(0, 10, text="3. Strategic Insights & News Alignment", new_x="LMARGIN", new_y="NEXT")
for article in news_list:
pdf.set_font("helvetica", "B", 11)
# multi_cell öncesi 'w=0' ve 'new_x/y' ayarlarını netleştiriyoruz
pdf.multi_cell(0, 8, text=f"Source: {article['source']} - {article['title']}", new_x="LMARGIN", new_y="NEXT")
pdf.set_font("helvetica", "I", 10)
# Hata buradaydı: w=0 kullanarak tüm genişliği almasını ve satır sonu yapmasını sağlıyoruz
pdf.multi_cell(0, 6, text=f"Model Insight: {article['model_comment']}", new_x="LMARGIN", new_y="NEXT")
pdf.ln(3)
return bytes(pdf.output())
# --- CONFIGURATION ---
st.set_page_config(
page_title="ClimateVision 2030 | Strategic Decision Intelligence",
page_icon="🌍",
layout="wide",
initial_sidebar_state="expanded"
)
# --- CUSTOM UI STYLING (Senior UI/UX) ---
st.markdown("""
<style>
.main { background-color: #f8f9fa; }
.stMetric { background-color: #ffffff; padding: 15px; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }
.status-badge { padding: 5px 12px; border-radius: 20px; font-weight: bold; font-size: 14px; }
.paris-compliant { background-color: #d4edda; color: #155724; }
.risk-alert { background-color: #fff3cd; color: #856404; }
.non-compliant { background-color: #f8d7da; color: #721c24; }
</style>
""", unsafe_allow_html=True)
# --- SIDEBAR NAVIGATION ---
def sidebar_navigation():
# Yer tutucu yerine kendi profesyonel görselini ekle
try:
st.sidebar.image("logo.png", use_container_width=True)
except:
# Görsel yüklenemezse şık bir yazı göster (Fallback)
st.sidebar.title("🌍 CLIMATE VISION 2030")
st.sidebar.markdown("---")
# ... (Diğer kodlar aynı kalacak)
page = st.sidebar.radio(
"Strategic Pillars",
["🏠 Strategic Overview",
"🔮 2030 Projection Engine",
"⚖️ Paris GAP Analysis",
"🧪 What-If Scenario Lab",
"📈 Model X-Ray (XAI)"]
)
st.sidebar.markdown("---")
st.sidebar.info("**Asset Note:** Model Status: Production Ready (v1.2.4)")
st.sidebar.caption(f"Last Intelligence Sync: {datetime.now().strftime('%Y-%m-%d')}")
return page
# --- PLACEHOLDER FUNCTIONS FOR PAGES ---
def show_overview():
st.title("🏠 Strategic Overview")
st.subheader("Global Emission Landscape & BAU Momentum")
st.markdown("""
*Executive Summary:* This module analyzes historical trajectories (1970-2024) and
identifies **Business-as-Usual (BAU)** trends across global economies.
""")
# GIS Map and Global KPIs will be here in Step 2.
st.info("Global Map and KPI metrics loading...")
def show_overview():
# --- PAGE HEADER ---
st.title("🏠 Strategic Overview")
st.markdown("""
<p style='font-size: 1.2rem; color: #555;'>
Analyze the <b>Global Atmospheric Load</b> and historical emission trajectories.
This module identifies structural trends and the <b>Business-as-Usual (BAU)</b> momentum
required for high-level policy auditing.
</p>
""", unsafe_allow_html=True)
# --- TOP LEVEL METRICS (KPIs) ---
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric(label="Global Emission Load (2024)", value="54.2 GtCO2e", delta="1.2% vs Prev Year")
with col2:
st.metric(label="BAU Momentum", value="Increasing", delta="Critical", delta_color="inverse")
with col3:
st.metric(label="Decoupling Index", value="0.42", help="Measures the separation of GDP growth from emission growth.")
with col4:
st.metric(label="Atmospheric Tipping Point", value="~7 Years", help="Estimated time until 1.5°C carbon budget is exhausted.")
st.markdown("---")
# --- GLOBAL GIS MAP (CHOROPLETH) ---
st.subheader("🌍 Global Emission Intensity & Risk Mapping")
# Mock Data for GIS (Replace with your actual 'df_last_year' data)
map_data = pd.DataFrame({
'Country': ['USA', 'CHN', 'IND', 'DEU', 'TUR', 'BRA', 'RUS'],
'Emission': [5000, 12000, 3000, 700, 500, 1000, 1600],
'Risk_Score': [75, 90, 65, 40, 55, 30, 80]
})
fig_map = px.choropleth(
map_data,
locations="Country",
locationmode='ISO-3',
color="Emission",
hover_name="Country",
hover_data=["Risk_Score"],
color_continuous_scale=px.colors.sequential.YlOrRd,
labels={'Emission': 'MtCO2e'}
)
fig_map.update_layout(
margin={"r":0,"t":0,"l":0,"b":0},
geo=dict(showframe=False, showcoastlines=True, projection_type='equirectangular'),
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
)
st.plotly_chart(fig_map, use_container_width=True)
# --- STRATEGIC INSIGHTS SECTION ---
col_a, col_b = st.columns([1, 1])
with col_a:
st.subheader("📈 Macro-Economic Decoupling Analysis")
st.markdown("""
The **Decoupling Index** indicates how much a country's economic growth (GDP) has
separated from its greenhouse gas emissions.
- **Absolute Decoupling:** Emissions fall as GDP rises (Goal).
- **Relative Decoupling:** Emissions rise slower than GDP.
""")
# Placeholder for a Decoupling Chart
chart_data = pd.DataFrame(np.random.randn(20, 2), columns=['GDP Trend', 'Emission Trend'])
st.line_chart(chart_data)
with col_b:
st.subheader("🚨 Priority Tipping Points")
st.error("**High Risk Sector:** Power Industry (Decarbonization lag identified)")
st.warning("**Target Gap:** Global 2030 targets require a 45% reduction in CO2 vs 2010 levels.")
st.success("**Emerging Opportunity:** Rapid acceleration in Renewables in EU/China.")
st.markdown("---")
st.caption("Data Source: EDGAR (Emissions Database for Global Atmospheric Research) v8.0 | Verified by ClimateVision Engine")
def show_projection():
st.title("🔮 2030 Projection Engine")
st.subheader("Hybrid Intelligence: Prophet Trend + LSTM Residual Correction")
# Live filters and Prediction graph will be here in Step 3.
import joblib # Prophet modelleri için
# from tensorflow.keras.models import load_model # LSTM için (Korumaya alarak yorum satırı yaptım)
def show_projection():
st.title("🔮 2030 Projection Engine")
st.markdown("""
<p style='font-size: 1.1rem;'>
This engine utilizes <b>Hybrid Intelligence</b>:
<b>Prophet</b> for long-term trend decomposition and <b>LSTM (RNN)</b> for non-linear residual correction.
Generating high-fidelity atmospheric trajectories for 2030.
</p>
""", unsafe_allow_html=True)
# --- MODEL LOADING (CACHED) ---
@st.cache_resource
def load_hybrid_models():
# Gerçek projende:
# prophet_model = joblib.load('models/prophet_v1.pkl')
# lstm_model = load_model('models/lstm_v1.keras')
return "Models Loaded Successfully"
model_status = load_hybrid_models()
# --- SELECTION BAR ---
st.markdown("### 🛠️ Configuration & Inference")
col1, col2, col3 = st.columns([2, 2, 1])
with col1:
country = st.selectbox("Target Economy (Country/Region)",
["Global Total", "European Union", "USA", "China", "Turkey", "India"])
with col2:
sector = st.selectbox("Economic Sector",
["All Sectors", "Power Industry", "Transport", "Industrial Combustion", "Buildings", "Agriculture"])
with col3:
st.write("") # Boşluk
predict_btn = st.button("🔥 Generate 2030 Projection", use_container_width=True)
if predict_btn:
with st.spinner(f"Inference Mode: Analyzing {country} - {sector} trajectory..."):
# --- MOCK DATA GENERATION (Gerçek modellerini buraya bağlayacaksın) ---
years = np.arange(2010, 2031)
historical_data = np.random.uniform(450, 500, size=15) # 2010-2024
# Prophet Trend
prophet_trend = np.linspace(500, 540, 6) # 2025-2030
# LSTM Residual Correction (Hafif dalgalanma ekler)
lstm_correction = np.random.normal(0, 5, 6)
hybrid_forecast = prophet_trend + lstm_correction
# Confidence Interval Calculation
upper_bound = hybrid_forecast * 1.05
lower_bound = hybrid_forecast * 0.95
# --- VISUALIZATION (Plotly) ---
fig = go.Figure()
# Historical Line
fig.add_trace(go.Scatter(x=years[:15], y=historical_data, name="Historical Data",
line=dict(color='#2c3e50', width=3)))
# Confidence Interval (Shadow)
fig.add_trace(go.Scatter(
x=years[14:], y=upper_bound, mode='lines', line=dict(width=0), showlegend=False))
fig.add_trace(go.Scatter(
x=years[14:], y=lower_bound, mode='lines', line=dict(width=0),
fill='toself', fillcolor='rgba(46, 204, 113, 0.2)', name="95% Confidence Interval"))
# Forecast Line
fig.add_trace(go.Scatter(x=years[14:], y=np.concatenate([[historical_data[-1]], hybrid_forecast]),
name="Hybrid AI Forecast (2030)",
line=dict(color='#2ecc71', width=4, dash='dash')))
fig.update_layout(
title=f"Atmospheric Emission Trajectory: {country} ({sector})",
xaxis_title="Timeline", yaxis_title="MtCO2e",
hovermode="x unified", template="plotly_white",
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1)
)
st.plotly_chart(fig, use_container_width=True)
# --- INSIGHT CARDS ---
c1, c2, c3 = st.columns(3)
with c1:
st.success(f"**2030 Point Estimate:** {hybrid_forecast[-1]:.2f} MtCO2e")
with c2:
growth_rate = ((hybrid_forecast[-1] - historical_data[-1]) / historical_data[-1]) * 100
st.metric("Estimated Growth vs 2024", f"{growth_rate:.1f}%", delta_color="inverse")
with c3:
st.warning("**Model Confidence:** 92.4% (Based on Historical Variance)")
else:
st.info("Select a country and sector, then click the button to trigger the inference engine.")
st.markdown("---")
st.caption("Note: Hybrid models are retrained monthly to incorporate the latest atmospheric readings.")
def show_gap_analysis():
st.title("⚖️ Paris GAP Analysis")
st.markdown("""
**The Audit Layer:** Comparing 2030 Hybrid AI Forecasts against Nationally Determined Contributions (NDCs).
This section identifies the *Policy Gap* required to maintain the 1.5°C trajectory.
""")
# --- SIMULATED DATA & LOGIC ---
# Gerçek projede bir önceki sayfadaki 'hybrid_forecast' değerini session_state ile buraya taşıyabilirsin.
forecast_2030 = 540.0 # Örnek tahmin
paris_target = 380.0 # 2010 seviyelerine göre %45 azaltım hedefi (Örnek)
gap = forecast_2030 - paris_target
gap_percentage = (gap / forecast_2030) * 100
# --- STATUS BADGES ---
st.markdown("### 🛡️ Compliance Audit Status")
if gap <= 0:
st.markdown('<span class="status-badge paris-compliant">✅ PARIS COMPLIANT</span>', unsafe_allow_html=True)
elif 0 < gap < 50:
st.markdown('<span class="status-badge risk-alert">⚠️ AT RISK</span>', unsafe_allow_html=True)
else:
st.markdown('<span class="status-badge non-compliant">🚨 NON-COMPLIANT</span>', unsafe_allow_html=True)
# --- GAUGE CHART & METRICS ---
col1, col2 = st.columns([1, 1])
with col1:
fig_gauge = go.Figure(go.Indicator(
mode = "gauge+number",
value = gap,
domain = {'x': [0, 1], 'y': [0, 1]},
title = {'text': "Reduction Gap (MtCO2e)"},
gauge = {
'axis': {'range': [None, 300]},
'bar': {'color': "#e74c3c"},
'steps': [
{'range': [0, 50], 'color': "#fff3cd"},
{'range': [50, 300], 'color': "#f8d7da"}
],
'threshold': {'line': {'color': "black", 'width': 4}, 'thickness': 0.75, 'value': 250}
}
))
st.plotly_chart(fig_gauge, use_container_width=True)
with col2:
st.write("### Strategic Audit Summary")
st.metric("Total Mitigation Gap", f"{gap:.1f} MtCO2e", f"{gap_percentage:.1f}% Reduction Needed", delta_color="inverse")
st.info(f"""
**Insight:** To bridge this gap, the selected economy must accelerate its
decarbonization rate by **2.4x** compared to the historical BAU trend.
""")
def show_what_if_lab():
st.title("🧪 What-If Scenario Laboratory")
st.subheader("Policy Intervention Simulation")
# --- SIDEBAR OR TOP PANEL SLIDERS ---
with st.expander("🛠️ Intervention Control Panel", expanded=True):
c1, c2, c3 = st.columns(3)
with c1:
renewables = st.slider("Renewable Energy Acceleration (%)", 0, 100, 20)
with c2:
carbon_tax = st.slider("Carbon Tax Increase ($/ton)", 0, 250, 50)
with c3:
tech_leap = st.select_slider("Technological Leap (CCUS)", options=["None", "Low", "Moderate", "Aggressive"])
# --- SIMULATION LOGIC ---
# Müdahalelerin tahmini etkisini hesaplayan basit bir fonksiyon
reduction_impact = (renewables * 0.5) + (carbon_tax * 0.2) + (30 if tech_leap == "Aggressive" else 10)
base_forecast_2030 = 540.0
simulated_2030 = base_forecast_2030 - reduction_impact
# Prosperity Index calculation (Logic: Growth vs. Sustainability)
prosperity_score = (100 - (simulated_2030 / 10)) + (renewables * 0.1)
# --- COMPARISON CHART ---
fig_sim = go.Figure()
fig_sim.add_trace(go.Bar(x=['BAU Forecast', 'Post-Intervention'],
y=[base_forecast_2030, simulated_2030],
marker_color=['#95a5a6', '#2ecc71']))
fig_sim.update_layout(title="Policy Impact Assessment (2030 Projection)")
st.plotly_chart(fig_sim, use_container_width=True)
# --- GREEN PROSPERITY INDEX ---
st.markdown("---")
st.subheader("🍃 Green Prosperity Index (GPI)")
st.progress(min(max(prosperity_score/100, 0.0), 1.0))
st.write(f"The simulated policies result in a Prosperity Score of **{prosperity_score:.1f}/100**.")
def show_xai():
st.title("📈 Model X-Ray (Explainable AI)")
st.markdown("""
**Transparency Layer:** This module provides an 'X-Ray' view of our Hybrid Intelligence.
By analyzing model residuals and feature dominance, we ensure that every 2030 projection is
statistically grounded and explainable.
""")
# News Data
news_items = [
{
"title": "EU Tightens Carbon Credit Framework for 2030",
"summary": "The European Commission announced a stricter framework for carbon credits by 2030 to normalize the Emissions Trading System (ETS).",
"source": "Reuters",
"search_query": "Reuters EU Carbon Credit Framework 2030",
"sentiment": "positive",
"alignment_score": 92,
"model_comment": "This policy change aligns 92% with our 'Low Emission' scenario and carbon price surge projections."
},
{
"title": "Global Supply Chain Disruptions Impacting Solar Parts",
"summary": "Global logistics crises are causing significant delays in solar panel component shipments, affecting renewable targets.",
"source": "Bloomberg",
"search_query": "Bloomberg Solar Supply Chain Disruptions 2030",
"sentiment": "negative",
"alignment_score": 45,
"model_comment": "Caution: Supply chain risks may exert downward pressure on our 2030 renewable capacity forecasts."
}
]
tab1, tab2, tab3 = st.tabs(["🔍 Diagnostic Intelligence", "🧬 Feature Dominance", "📰 Policy News Agent"])
with tab1:
st.subheader("Model Röntgeni: Residuals Analysis")
st.info("Visualizing how the LSTM layer corrected the Prophet baseline residuals.")
# Simulated Residuals Plot
res_x = np.linspace(0, 100, 100)
res_y = np.random.normal(0, 2, 100) # Gaussian noise centered at zero
fig_res = px.scatter(x=res_x, y=res_y, labels={'x': 'Inference Timeline', 'y': 'Error Variance (Residuals)'},
title="Hybrid Model Residual Distribution", opacity=0.6)
fig_res.add_hline(y=0, line_dash="dash", line_color="red")
fig_res.update_traces(marker=dict(color='#34495e'))
st.plotly_chart(fig_res, use_container_width=True)
st.write("""
**Strategic Insight:** The residuals are randomly distributed around zero, confirming that
the **LSTM residual correction** successfully captured the non-linear variances that
Prophet's trend baseline missed.
""")
with tab2:
st.subheader("Inference Drivers: Global Feature Importance")
# Mock Feature Importance (Based on Project Logic)
importance_data = pd.DataFrame({
'Feature': ['Historical Momentum', 'Energy Sector Intensity', 'GDP Decoupling Rate', 'CH4 Concentration', 'Land Use Changes'],
'Impact Score': [0.45, 0.25, 0.15, 0.10, 0.05]
}).sort_values(by='Impact Score', ascending=True)
fig_imp = px.bar(importance_data, x='Impact Score', y='Feature', orientation='h',
title="Feature Dominance in 2030 Projections",
color_discrete_sequence=['#2ecc71'])
st.plotly_chart(fig_imp, use_container_width=True)
st.write("> **Asset Note:** 'Historical Momentum' remains the primary driver, followed closely by 'Energy Sector Intensity'.")
with tab3:
st.subheader("📰 Strategic News Agent (Scraped Intelligence)")
st.info("This module analyzes real-time policy news to validate our 2030 projections.")
# Bu döngü ve içindekiler MUTLAKA 'with tab3' altında girintili olmalı
for article in news_items:
icon = "🟢" if article["sentiment"] == "positive" else "🔴"
status = "SUPPORTIVE" if article["sentiment"] == "positive" else "RISK FACTOR"
reliable_link = f"https://www.google.com/search?q={article['search_query'].replace(' ', '+')}"
with st.expander(f"{icon} {article['source']}: {article['title']}"):
col1, col2 = st.columns([2, 1])
with col1:
st.write(f"**Summary:** {article['summary']}")
st.link_button("Verify Source on Google News", reliable_link)
with col2:
st.metric("Model Alignment", f"{article['alignment_score']}%")
st.caption(f"**Status:** {status}")
# Model Insight'ı her haberin içine (expander altına) koyuyoruz
st.divider()
st.markdown(f"🔍 **Model Insight:** {article['model_comment']}")
# --- FINAL REPORTING EXPORT (ACTIVE VERSION) ---
st.markdown("---")
st.subheader("📄 Decision Support Report")
# Rapor için gerekli güncel verileri hazırla
# Not: Gerçek verileri yukarıdaki analizlerden çekebilirsin
report_data = {
"country": "Selected Nation",
"sector": "All Sectors",
"forecast": 540.25,
"gap": 160.25,
"status": "DANGER: NON-COMPLIANT"
}
st.caption("Strategic reports include 2030 projections, GAP analysis, and explainability audits.")
# Bu kısmı Tab'ların dışına, en alta koyuyoruz
pdf_bytes = create_pdf_report(
report_data["country"],
report_data["sector"],
report_data["forecast"],
report_data["gap"],
report_data["status"],
news_items # <--- Tab 3'te tanımladığın haber listesini buraya ekledik
)
st.download_button(
label="📥 Download Executive Summary (PDF)",
data=pdf_bytes,
file_name=f"ClimateVision_Full_Report_{datetime.now().strftime('%Y%m%d')}.pdf",
mime="application/pdf",
width="stretch"
)
# --- MAIN APP LOGIC ---
def main():
selected_page = sidebar_navigation()
if selected_page == "🏠 Strategic Overview":
show_overview()
elif selected_page == "🔮 2030 Projection Engine":
show_projection()
elif selected_page == "⚖️ Paris GAP Analysis":
show_gap_analysis()
elif selected_page == "🧪 What-If Scenario Lab":
show_what_if_lab()
elif selected_page == "📈 Model X-Ray (XAI)":
show_xai()
if __name__ == "__main__":
main()