Spaces:
Runtime error
Runtime error
File size: 12,117 Bytes
32c2587 dcf465d e872da8 dcf465d f039650 dcf465d ddd101e e872da8 db58fdb e872da8 db58fdb dbf76b6 db58fdb dbf76b6 bcd0e3c dbf76b6 db58fdb dbf76b6 db58fdb dbf76b6 db58fdb dbf76b6 e872da8 dbf76b6 e872da8 dbf76b6 e872da8 dbf76b6 e872da8 dbf76b6 e872da8 dbf76b6 e872da8 dbf76b6 e872da8 dbf76b6 e872da8 dbf76b6 ddd101e dcf465d f8842a2 e872da8 dcf465d dbf76b6 dcf465d db58fdb e872da8 db58fdb dcf465d e8a8241 db58fdb e8a8241 dcf465d a2875f8 db58fdb dcf465d f8842a2 dcf465d 61186ad dcf465d |
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
import gradio as gr
import random
import json
import fastapi
from fastapi import FastAPI
# Create a FastAPI app
app = FastAPI()
# Sample country data with random progress percentages
def generate_data():
return {
"MX": {"name": "Mexico", "percent": random.randint(10, 90)},
"AR": {"name": "Argentina", "percent": random.randint(10, 90)},
"CO": {"name": "Colombia", "percent": random.randint(10, 90)},
"CL": {"name": "Chile", "percent": random.randint(10, 90)},
"PE": {"name": "Peru", "percent": random.randint(10, 90)},
"ES": {"name": "Spain", "percent": random.randint(10, 90)},
"BR": {"name": "Brazil", "percent": random.randint(10, 90)},
"VE": {"name": "Venezuela", "percent": random.randint(10, 90)},
"EC": {"name": "Ecuador", "percent": random.randint(10, 90)},
"BO": {"name": "Bolivia", "percent": random.randint(10, 90)},
"PY": {"name": "Paraguay", "percent": random.randint(10, 90)},
"UY": {"name": "Uruguay", "percent": random.randint(10, 90)},
"CR": {"name": "Costa Rica", "percent": random.randint(10, 90)},
"PA": {"name": "Panama", "percent": random.randint(10, 90)},
"DO": {"name": "Dominican Republic", "percent": random.randint(10, 90)},
"GT": {"name": "Guatemala", "percent": random.randint(10, 90)},
"HN": {"name": "Honduras", "percent": random.randint(10, 90)},
"SV": {"name": "El Salvador", "percent": random.randint(10, 90)},
"NI": {"name": "Nicaragua", "percent": random.randint(10, 90)},
"CU": {"name": "Cuba", "percent": random.randint(10, 90)}
}
# HTML template - avoiding f-strings with JavaScript template literals
HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Latin America & Spain Map</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
body {
margin: 0;
padding: 20px;
background-color: #111;
color: #fff;
font-family: sans-serif;
}
h1 {
margin-bottom: 20px;
}
#map-container {
width: 100%;
height: 600px;
position: relative;
}
#tooltip {
position: absolute;
background-color: rgba(0, 0, 0, 0.8);
border-radius: 5px;
padding: 8px;
color: white;
font-size: 12px;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s;
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body>
<h1>Latin America & Spain Progress Map</h1>
<div id="map-container"></div>
<div id="tooltip"></div>
<script>
// Country data from Python - will be replaced
const countryData = COUNTRY_DATA_PLACEHOLDER;
document.addEventListener('DOMContentLoaded', function() {
// Set up dimensions
const container = document.getElementById('map-container');
const width = container.clientWidth;
const height = container.clientHeight;
// Create SVG
const svg = d3.select('#map-container')
.append('svg')
.attr('width', width)
.attr('height', height)
.attr('viewBox', '0 0 ' + width + ' ' + height);
// Create color scale
const colorScale = d3.scaleLinear()
.domain([0, 100])
.range(['#4a1942', '#f32b7b']);
// Set up projection focused on Latin America and Spain
const projection = d3.geoMercator()
.center([-60, 0])
.scale(width / 5)
.translate([width / 2, height / 2]);
const path = d3.geoPath().projection(projection);
// Tooltip setup
const tooltip = d3.select('#tooltip');
// Load GeoJSON data
d3.json('https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson')
.then(function(data) {
// Draw countries
svg.selectAll('path')
.data(data.features)
.enter()
.append('path')
.attr('d', path)
.attr('stroke', '#f32b7b')
.attr('stroke-width', 1)
.attr('fill', function(d) {
// Get the ISO code from the properties
const iso = d.properties.iso_a2;
if (countryData[iso]) {
return colorScale(countryData[iso].percent);
}
return '#2d3748'; // Default gray for other countries
})
.on('mouseover', function(event, d) {
const iso = d.properties.iso_a2;
d3.select(this)
.attr('stroke', '#4a1942')
.attr('stroke-width', 2);
if (countryData[iso]) {
tooltip.style('opacity', 1)
.style('left', (event.pageX + 15) + 'px')
.style('top', (event.pageY + 15) + 'px')
.html('<strong>' + countryData[iso].name + '</strong><br/>' +
'Progress: ' + countryData[iso].percent + '%');
}
})
.on('mousemove', function(event) {
tooltip.style('left', (event.pageX + 15) + 'px')
.style('top', (event.pageY + 15) + 'px');
})
.on('mouseout', function() {
d3.select(this)
.attr('stroke', '#f32b7b')
.attr('stroke-width', 1);
tooltip.style('opacity', 0);
});
// Add a legend
const legendWidth = Math.min(width - 40, 200);
const legendHeight = 15;
const legendX = width - legendWidth - 20;
const legend = svg.append('g')
.attr('transform', 'translate(' + legendX + ', 30)');
// Create gradient for legend
const defs = svg.append('defs');
const gradient = defs.append('linearGradient')
.attr('id', 'dataGradient')
.attr('x1', '0%')
.attr('y1', '0%')
.attr('x2', '100%')
.attr('y2', '0%');
gradient.append('stop')
.attr('offset', '0%')
.attr('stop-color', '#4a1942');
gradient.append('stop')
.attr('offset', '100%')
.attr('stop-color', '#f32b7b');
// Add legend title
legend.append('text')
.attr('x', legendWidth / 2)
.attr('y', -10)
.attr('text-anchor', 'middle')
.attr('font-size', '12px')
.attr('fill', '#f1f5f9')
.text('Progress');
// Add legend rectangle
legend.append('rect')
.attr('width', legendWidth)
.attr('height', legendHeight)
.attr('rx', 2)
.attr('ry', 2)
.style('fill', 'url(#dataGradient)');
// Add legend labels
legend.append('text')
.attr('x', 0)
.attr('y', legendHeight + 15)
.attr('text-anchor', 'start')
.attr('font-size', '10px')
.attr('fill', '#94a3b8')
.text('0%');
legend.append('text')
.attr('x', legendWidth / 2)
.attr('y', legendHeight + 15)
.attr('text-anchor', 'middle')
.attr('font-size', '10px')
.attr('fill', '#94a3b8')
.text('50%');
legend.append('text')
.attr('x', legendWidth)
.attr('y', legendHeight + 15)
.attr('text-anchor', 'end')
.attr('font-size', '10px')
.attr('fill', '#94a3b8')
.text('100%');
})
.catch(function(error) {
console.error('Error loading or rendering the map:', error);
container.innerHTML = '<div style="color: white; text-align: center;">Error loading map: ' + error.message + '</div>';
});
// Handle window resize
window.addEventListener('resize', function() {
const width = container.clientWidth;
// Update SVG dimensions
d3.select('svg')
.attr('width', width)
.attr('viewBox', '0 0 ' + width + ' ' + height);
// Update projection
projection.scale(width / 5)
.translate([width / 2, height / 2]);
// Update paths
d3.selectAll('path').attr('d', path);
// Update legend position
const legendWidth = Math.min(width - 40, 200);
const legendX = width - legendWidth - 20;
d3.select('g').attr('transform', 'translate(' + legendX + ', 30)');
});
});
</script>
</body>
</html>
"""
# Route to serve the map visualization
@app.get("/d3-map")
async def serve_map():
# Generate random data
country_data = generate_data()
# Convert to JSON for JavaScript
country_data_json = json.dumps(country_data)
# Replace the placeholder with actual data
html_content = HTML_TEMPLATE.replace("COUNTRY_DATA_PLACEHOLDER", country_data_json)
return fastapi.responses.HTMLResponse(content=html_content)
# Create a simple Gradio interface with an iframe
def create_iframe():
# Add a random parameter to force reload
random_param = random.randint(1, 10000)
return '<iframe src="/d3-map?t={}" style="width:100%; height:650px; border:none;"></iframe>'.format(random_param)
# Create the Gradio blocks
with gr.Blocks(theme=gr.themes.Soft(primary_hue="pink", secondary_hue="purple")) as demo:
gr.Markdown("# Latin America & Spain Progress Map")
iframe_output = gr.HTML(create_iframe())
# Refresh button to generate new random data
def refresh():
return create_iframe()
gr.Button("Generate New Data").click(fn=refresh, outputs=iframe_output)
# Mount the Gradio app to the FastAPI app
gr.mount_gradio_app(app, demo, path="/")
# Start the server
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860) |