Spaces:
Sleeping
Sleeping
File size: 5,726 Bytes
be096d1 6e9dc4d 99101f6 35509b3 ce5e315 ff0d30b be096d1 99101f6 be096d1 ff0d30b 61f85b2 ff0d30b 35509b3 ff0d30b 61f85b2 ff0d30b 35509b3 ff0d30b 61f85b2 ff0d30b 35509b3 99101f6 ff0d30b ce5e315 61f85b2 ce5e315 99101f6 61f85b2 ff0d30b 99101f6 df1519d 61f85b2 ff0d30b 61f85b2 ff0d30b 5f830c6 61f85b2 ff0d30b 6e9dc4d 61f85b2 ff0d30b 6e9dc4d 61f85b2 ff0d30b 61f85b2 ff0d30b 35509b3 61f85b2 ff0d30b 61f85b2 35509b3 61f85b2 35509b3 61f85b2 ff0d30b 61f85b2 ff0d30b 99101f6 ff0d30b 61f85b2 35509b3 61f85b2 35509b3 99101f6 ff0d30b 61f85b2 35509b3 ff0d30b 99101f6 ff0d30b 99101f6 61f85b2 35509b3 61f85b2 be096d1 35509b3 ff0d30b 61f85b2 35509b3 ff0d30b 61f85b2 ff0d30b 99101f6 35509b3 61f85b2 35509b3 61f85b2 ff0d30b 61f85b2 35509b3 61f85b2 ff0d30b 35509b3 ff0d30b 61f85b2 99101f6 61f85b2 ff0d30b 61f85b2 35509b3 61f85b2 35509b3 be096d1 39ee1aa a4d0bd6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
import gradio as gr
import pandas as pd
import folium
from geopy.geocoders import Nominatim
import tempfile
import warnings
from datetime import datetime
warnings.filterwarnings("ignore")
# Historical Basemap Configuration
HISTORICAL_BASEMAPS = {
"1700s": {
"url": "https://map1.davidrumsey.com/tiles/rumsey/SDSC1790/{z}/{x}/{y}.png",
"attr": "Rumsey 1794",
"year_range": (1700, 1800),
"default_zoom": 2
},
"1800s": {
"url": "https://map1.davidrumsey.com/tiles/rumsey/SDSC1860/{z}/{x}/{y}.png",
"attr": "Colton 1865",
"year_range": (1801, 1900),
"default_zoom": 3
},
"Early 1900s": {
"url": "https://stamen-tiles.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png",
"attr": "Stamen 1915",
"year_range": (1901, 1920),
"default_zoom": 4
}
}
class HistoricalGeocoder:
def __init__(self):
self.geolocator = Nominatim(user_agent="historical_mapper_v4")
self.cache = {}
def get_coords(self, location: str, year: int):
"""Get coordinates with simple historical adjustments"""
cache_key = f"{location}_{year}"
if cache_key in self.cache:
return self.cache[cache_key]
try:
result = self.geolocator.geocode(location, timeout=10)
if not result:
return None
lat, lon = result.latitude, result.longitude
# Simple historical adjustments (example only)
if year < 1800:
# Older maps often had shifted coordinates
lon += 0.2
lat += 0.1
elif year < 1900:
lon += 0.1
self.cache[cache_key] = (lat, lon)
return (lat, lon)
except Exception as e:
print(f"Geocoding failed: {str(e)}")
return None
def create_historical_map(df, location_col, year):
geocoder = HistoricalGeocoder()
# Select appropriate basemap
basemap = next(
(bm for bm in HISTORICAL_BASEMAPS.values()
if bm["year_range"][0] <= year <= bm["year_range"][1]),
HISTORICAL_BASEMAPS["1800s"]
)
# Create map
m = folium.Map(
location=[40, 0],
zoom_start=basemap["default_zoom"],
tiles=basemap["url"],
attr=basemap["attr"],
control_scale=True
)
# Add all basemaps as layers
for name, config in HISTORICAL_BASEMAPS.items():
if config["url"] != basemap["url"]:
folium.TileLayer(
tiles=config["url"],
attr=config["attr"],
name=f"{name} ({config['year_range'][0]}-{config['year_range'][1]})",
overlay=False
).add_to(m)
# Add markers
coords = []
for loc in df[location_col].dropna().unique():
point = geocoder.get_coords(str(loc), year)
if point:
folium.Marker(
location=point,
popup=f"<b>{loc}</b><br><i>As of {year}</i>",
icon=folium.Icon(
color="red" if year < 1850 else "blue",
icon="history" if year < 1850 else "info-sign",
prefix="fa"
)
).add_to(m)
coords.append(point)
# Add layer control and fit bounds
folium.LayerControl().add_to(m)
if coords:
m.fit_bounds(coords)
return m._repr_html_()
def process_file(file_obj, location_col, year):
try:
# Read file
df = pd.read_excel(file_obj.name)
# Validate column
if location_col not in df.columns:
return None, f"Column '{location_col}' not found"
# Create map
map_html = create_historical_map(df, location_col, year)
# Save processed data
with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as tmp:
df.to_excel(tmp.name, index=False)
processed_path = tmp.name
return (
f"<div style='width:100%; height:70vh'>{map_html}</div>",
f"Map Year: {year}\nLocations: {len(df)}",
processed_path
)
except Exception as e:
return None, f"Error: {str(e)}", None
# Gradio Interface
with gr.Blocks(title="Historical Map Explorer", theme=gr.themes.Soft()) as app:
gr.Markdown("# Historical Location Mapper")
with gr.Row():
with gr.Column():
file_input = gr.File(
label="1. Upload Excel File",
file_types=[".xlsx", ".xls"],
type="filepath"
)
location_col = gr.Textbox(
label="2. Location Column Name",
value="location",
interactive=True
)
year = gr.Slider(
label="3. Select Map Year",
minimum=1700,
maximum=1920,
value=1850,
step=1
)
btn = gr.Button("Generate Map", variant="primary")
with gr.Column():
map_display = gr.HTML(
label="Historical Map",
value="<div style='text-align:center;padding:2em;color:gray'>"
"Map will appear here</div>"
)
stats = gr.Textbox(label="Map Info")
download = gr.File(label="Download Processed Data", visible=True)
btn.click(
process_file,
inputs=[file_input, location_col, year],
outputs=[map_display, stats, download]
)
if __name__ == "__main__":
app.launch() |