history_map / app.py
ambrosfitz's picture
Update app.py
2f1ae68 verified
import gradio as gr
import networkx as nx
import matplotlib.pyplot as plt
from pathlib import Path
import spacy
import re
# Load spaCy model
try:
nlp = spacy.load("en_core_web_sm")
except OSError:
print("Downloading spaCy model...")
import subprocess
subprocess.run(["python", "-m", "spacy", "download", "en_core_web_sm"])
nlp = spacy.load("en_core_web_sm")
# Define categories and their colors with better contrast
CATEGORIES = {
"Main Theme": "#4287f5", # Bright blue
"Event": "#42f54b", # Bright green
"Person": "#f542aa", # Pink
"Law": "#f5d442", # Yellow
"Concept": "#f54242" # Red
}
# Sample historical data for Unit 5 (1844-1877)
HISTORICAL_DATA = {
"civil war": {
"category": "Main Theme",
"related": [
("Abraham Lincoln", "Person"),
("Emancipation Proclamation", "Law"),
("Confederate States", "Concept"),
("Union Army", "Concept"),
("Battle of Gettysburg", "Event"),
("Slavery", "Main Theme"),
("Robert E. Lee", "Person"),
("Ulysses S. Grant", "Person")
]
},
"reconstruction": {
"category": "Main Theme",
"related": [
("13th Amendment", "Law"),
("14th Amendment", "Law"),
("15th Amendment", "Law"),
("Freedmen's Bureau", "Concept"),
("Andrew Johnson", "Person"),
("Black Codes", "Law"),
("Radical Republicans", "Concept"),
("Carpetbaggers", "Concept")
]
},
"manifest destiny": {
"category": "Main Theme",
"related": [
("Mexican-American War", "Event"),
("Oregon Territory", "Concept"),
("California Gold Rush", "Event"),
("James K. Polk", "Person"),
("Treaty of Guadalupe Hidalgo", "Law"),
("Westward Expansion", "Concept"),
("Native American Displacement", "Event"),
("Mexican Cession", "Event")
]
}
}
def categorize_term(term):
"""Categorize a term based on predefined data and NER."""
term_lower = term.lower()
# Check predefined categories first
if term_lower in HISTORICAL_DATA:
return HISTORICAL_DATA[term_lower]["category"]
# Use spaCy for NER
doc = nlp(term)
for ent in doc.ents:
if ent.label_ == "PERSON":
return "Person"
elif ent.label_ == "EVENT" or ent.label_ == "DATE":
return "Event"
elif ent.label_ == "LAW" or ent.label_ == "ORG":
return "Law"
# Default to Concept if no other category is found
return "Concept"
def get_related_terms(term):
"""Get related terms for a given historical term."""
term_lower = term.lower()
if term_lower in HISTORICAL_DATA:
return HISTORICAL_DATA[term_lower]["related"]
# If term not in predefined data, return some general connections
# based on the time period
general_connections = [
("Civil War", "Main Theme"),
("Reconstruction", "Main Theme"),
("Abraham Lincoln", "Person"),
("Slavery", "Concept"),
("United States", "Concept")
]
return general_connections[:5] # Limit to 5 connections
def generate_context_map(term):
"""Generate a network visualization for the given term."""
if not term or not term.strip():
return None
# Create graph
G = nx.Graph()
# Add main term
main_term = term.strip()
term_category = categorize_term(main_term)
G.add_node(main_term, category=term_category)
# Add related terms
related_terms = get_related_terms(main_term)
for related_term, category in related_terms:
if related_term.lower() != main_term.lower():
G.add_node(related_term, category=category)
G.add_edge(main_term, related_term)
# Create visualization
plt.figure(figsize=(12, 12))
plt.clf()
# Set light background for better contrast
plt.gca().set_facecolor('#ffffff')
plt.gcf().set_facecolor('#ffffff')
# Create layout
pos = nx.spring_layout(G, k=1.5, iterations=50)
# Draw nodes for each category
for category, color in CATEGORIES.items():
node_list = [node for node, attr in G.nodes(data=True)
if attr.get('category') == category]
if node_list:
nx.draw_networkx_nodes(G, pos,
nodelist=node_list,
node_color=color,
node_size=3000,
alpha=0.7)
# Draw edges
nx.draw_networkx_edges(G, pos, edge_color='gray', width=2, alpha=0.6)
# Add labels with better formatting
labels = nx.draw_networkx_labels(G, pos,
font_size=10,
font_weight='bold',
font_color='black')
# Add title and legend
plt.title(f"Historical Context Map for '{main_term}'",
fontsize=16,
pad=20)
# Add category legend
legend_elements = [plt.Line2D([0], [0], marker='o', color='w',
markerfacecolor=color, markersize=10,
label=category)
for category, color in CATEGORIES.items()]
plt.legend(handles=legend_elements, loc='upper left',
bbox_to_anchor=(1, 1))
plt.tight_layout()
return plt.gcf()
# Create Gradio interface
iface = gr.Interface(
fn=generate_context_map,
inputs=gr.Textbox(
label="Enter a historical term from Unit 5 (1844-1877)",
placeholder="e.g., Civil War, Abraham Lincoln, Reconstruction"
),
outputs=gr.Plot(),
title="Historical Context Mapper",
description="""Enter a term from Unit 5 (1844-1877) to see its historical context and connections.
The visualization will show how the term relates to key events, people, laws, and concepts from this period.""",
examples=[
["Civil War"],
["Reconstruction"],
["Manifest Destiny"],
["Abraham Lincoln"],
["Emancipation Proclamation"]
],
theme="default"
)
if __name__ == "__main__":
iface.launch()