Spaces:
Running
Running
Update app_pyvis_new.py
Browse files- app_pyvis_new.py +60 -35
app_pyvis_new.py
CHANGED
|
@@ -18,19 +18,35 @@ def load_data():
|
|
| 18 |
return f"Error loading CSV: {e}"
|
| 19 |
return "Data already loaded."
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
# --- LOGIC FUNCTIONS ---
|
| 22 |
|
| 23 |
def plot_cgraph_pyvis(grp):
|
| 24 |
if not grp:
|
| 25 |
return "<div style='padding:20px; text-align:center; color:gray;'>No graph data available for this event.</div>"
|
| 26 |
try:
|
| 27 |
-
net = Network(notebook=False, directed=True, height="
|
| 28 |
edge_colors_dict = {"causes": "#e74c3c", "prevents": "#2ecc71"}
|
| 29 |
|
| 30 |
for src, rel, tgt in grp:
|
| 31 |
-
|
| 32 |
-
net.add_node(str(
|
| 33 |
-
net.add_node(str(tgt), label=str(tgt), shape="circle", color="#add8e6", font={'size': 14, 'color': 'black'})
|
| 34 |
color = edge_colors_dict.get(str(rel).lower(), "#95a5a6")
|
| 35 |
net.add_edge(str(src), str(tgt), label=str(rel), color=color, width=2)
|
| 36 |
|
|
@@ -55,61 +71,70 @@ def update_row_dropdown(disaster_type, country):
|
|
| 55 |
def display_info(selected_row_str):
|
| 56 |
load_data()
|
| 57 |
if not selected_row_str or selected_row_str == 'Select a Disaster Event':
|
| 58 |
-
return '
|
| 59 |
|
| 60 |
row_data = df[df['DisNo.'] == selected_row_str]
|
| 61 |
if not row_data.empty:
|
| 62 |
row_data = row_data.squeeze()
|
| 63 |
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
"
|
| 67 |
-
"
|
| 68 |
-
"
|
| 69 |
-
"
|
| 70 |
-
"
|
| 71 |
-
"
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
| 75 |
causal_graph_caption = row_data.get('llama graph', '')
|
| 76 |
try:
|
| 77 |
grp = ast.literal_eval(causal_graph_caption) if causal_graph_caption else []
|
| 78 |
graph_html = plot_cgraph_pyvis(grp)
|
| 79 |
-
iframe = f"<iframe srcdoc='{graph_html}' width='100%' height='
|
| 80 |
except:
|
| 81 |
iframe = "<div>Invalid graph format.</div>"
|
| 82 |
|
| 83 |
-
return
|
| 84 |
return 'No valid data found.', '<div>No graph available.</div>'
|
| 85 |
|
| 86 |
# --- GRADIO UI BUILD ---
|
| 87 |
|
| 88 |
with gr.Blocks(title="Disaster Storylines Explorer") as interface:
|
| 89 |
-
#
|
| 90 |
gr.Markdown(
|
| 91 |
"""
|
| 92 |
-
## Disaster Storylines
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
| 96 |
"""
|
| 97 |
)
|
| 98 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
with gr.Row():
|
| 100 |
-
# Sidebar for Selection
|
| 101 |
with gr.Column(scale=1):
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
with gr.Tabs():
|
| 109 |
-
with gr.TabItem("Causal Graph"):
|
| 110 |
-
graph_box = gr.HTML()
|
| 111 |
-
with gr.TabItem("AI Storyline"):
|
| 112 |
-
story_box = gr.Markdown()
|
| 113 |
|
| 114 |
# --- INITIALIZATION AND HANDLERS ---
|
| 115 |
def init_app():
|
|
|
|
| 18 |
return f"Error loading CSV: {e}"
|
| 19 |
return "Data already loaded."
|
| 20 |
|
| 21 |
+
# --- UI HELPERS ---
|
| 22 |
+
|
| 23 |
+
def format_storyline_html(label, value):
|
| 24 |
+
"""Wraps a storyline section in an orange-themed box."""
|
| 25 |
+
if not value or str(value).strip() == "":
|
| 26 |
+
return ""
|
| 27 |
+
return f"""
|
| 28 |
+
<div style="margin-bottom: 20px; border-left: 5px solid #ff9800; padding-left: 15px;">
|
| 29 |
+
<div style="background-color: #fff3e0; padding: 5px 12px; font-weight: bold; color: #e65100; border-radius: 4px; display: inline-block; margin-bottom: 8px;">
|
| 30 |
+
{label}
|
| 31 |
+
</div>
|
| 32 |
+
<div style="font-size: 14px; line-height: 1.6; color: #333;">
|
| 33 |
+
{value}
|
| 34 |
+
</div>
|
| 35 |
+
</div>
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
# --- LOGIC FUNCTIONS ---
|
| 39 |
|
| 40 |
def plot_cgraph_pyvis(grp):
|
| 41 |
if not grp:
|
| 42 |
return "<div style='padding:20px; text-align:center; color:gray;'>No graph data available for this event.</div>"
|
| 43 |
try:
|
| 44 |
+
net = Network(notebook=False, directed=True, height="700px", width="100%", bgcolor="#ffffff")
|
| 45 |
edge_colors_dict = {"causes": "#e74c3c", "prevents": "#2ecc71"}
|
| 46 |
|
| 47 |
for src, rel, tgt in grp:
|
| 48 |
+
net.add_node(str(src), label=str(src), shape="circle", color="#ADD8E6", font={'size': 14, 'color': '#000000'})
|
| 49 |
+
net.add_node(str(tgt), label=str(tgt), shape="circle", color="#ADD8E6", font={'size': 14, 'color': '#000000'})
|
|
|
|
| 50 |
color = edge_colors_dict.get(str(rel).lower(), "#95a5a6")
|
| 51 |
net.add_edge(str(src), str(tgt), label=str(rel), color=color, width=2)
|
| 52 |
|
|
|
|
| 71 |
def display_info(selected_row_str):
|
| 72 |
load_data()
|
| 73 |
if not selected_row_str or selected_row_str == 'Select a Disaster Event':
|
| 74 |
+
return 'Select an event to see the narrative.', '<div>Select an event to see the graph.</div>'
|
| 75 |
|
| 76 |
row_data = df[df['DisNo.'] == selected_row_str]
|
| 77 |
if not row_data.empty:
|
| 78 |
row_data = row_data.squeeze()
|
| 79 |
|
| 80 |
+
# Build narrative with orange boxes
|
| 81 |
+
sections = [
|
| 82 |
+
("Key Information", row_data.get('key information', '')),
|
| 83 |
+
("Severity", row_data.get('severity', '')),
|
| 84 |
+
("Key Drivers", row_data.get('key drivers', '')),
|
| 85 |
+
("Impacts & Vulnerability", row_data.get('main impacts, exposure, and vulnerability', '')),
|
| 86 |
+
("Multi-Hazard Risks", row_data.get('likelihood of multi-hazard risks', '')),
|
| 87 |
+
("Best Practices", row_data.get('best practices for managing this risk', '')),
|
| 88 |
+
("Recovery Measures", row_data.get('recommendations and supportive measures for recovery', ''))
|
| 89 |
+
]
|
| 90 |
+
|
| 91 |
+
storyline_html = "".join(format_storyline_html(l, v) for l, v in sections)
|
| 92 |
+
|
| 93 |
+
# Build graph
|
| 94 |
causal_graph_caption = row_data.get('llama graph', '')
|
| 95 |
try:
|
| 96 |
grp = ast.literal_eval(causal_graph_caption) if causal_graph_caption else []
|
| 97 |
graph_html = plot_cgraph_pyvis(grp)
|
| 98 |
+
iframe = f"<iframe srcdoc='{graph_html}' width='100%' height='750px' style='border:1px solid #eee; border-radius:8px;'></iframe>"
|
| 99 |
except:
|
| 100 |
iframe = "<div>Invalid graph format.</div>"
|
| 101 |
|
| 102 |
+
return storyline_html, iframe
|
| 103 |
return 'No valid data found.', '<div>No graph available.</div>'
|
| 104 |
|
| 105 |
# --- GRADIO UI BUILD ---
|
| 106 |
|
| 107 |
with gr.Blocks(title="Disaster Storylines Explorer") as interface:
|
| 108 |
+
# Header Section
|
| 109 |
gr.Markdown(
|
| 110 |
"""
|
| 111 |
+
### Disaster Storylines & Causal Knowledge Graphs Explorer
|
| 112 |
+
Maintained by **Joint Research Centre (JRC)** Units E1, F7, and T5, this dashboard provides narratives and knowledge graphs for over 3,000 disaster events (EM-DAT).
|
| 113 |
+
These records were generated using a **Retrieval-Augmented Generation (RAG)** pipeline on **Europe Media Monitor (EMM)** news using **Meta-Llama-3-70B-Instruct** via **GPT@JRC**.
|
| 114 |
+
Graphs visualize simplified causal dynamics restricted to *'causes'* and *'prevents'* relationships.
|
| 115 |
+
Data and code are available via **Zenodo**: [https://doi.org/10.5281/zenodo.18598183](https://doi.org/10.5281/zenodo.18598183).
|
| 116 |
+
|
| 117 |
+
**Select a Disaster Type, a Country and an Event ID below to explore the AI-generated content!**
|
| 118 |
"""
|
| 119 |
)
|
| 120 |
|
| 121 |
+
# 1) Selectors: Full width horizontal row
|
| 122 |
+
with gr.Row():
|
| 123 |
+
disaster_type_dropdown = gr.Dropdown(choices=[''], label="1. Disaster Type", scale=1)
|
| 124 |
+
country_dropdown = gr.Dropdown(choices=[''], label="2. Country", scale=1)
|
| 125 |
+
row_dropdown = gr.Dropdown(choices=[], label="3. Select Disaster Event ID", interactive=True, scale=1)
|
| 126 |
+
|
| 127 |
+
gr.Markdown("---")
|
| 128 |
+
|
| 129 |
+
# 2) Main Content: Vertical Split (Narrative on Left, Graph on Right)
|
| 130 |
with gr.Row():
|
|
|
|
| 131 |
with gr.Column(scale=1):
|
| 132 |
+
gr.Markdown("### 📖 Narrative Storyline")
|
| 133 |
+
story_box = gr.HTML(value="<div style='color:gray;'>Select an event above to view the structured narrative.</div>")
|
| 134 |
+
|
| 135 |
+
with gr.Column(scale=1):
|
| 136 |
+
gr.Markdown("### 🕸️ Causal Knowledge Graph")
|
| 137 |
+
graph_box = gr.HTML(value="<div style='color:gray;'>Select an event above to view the knowledge graph.</div>")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
# --- INITIALIZATION AND HANDLERS ---
|
| 140 |
def init_app():
|