{"spec_id":"heatmap-geographic","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nheatmap-geographic: Geographic Heatmap for Spatial Density\nLibrary: letsplot 4.9.0 | Python 3.13.13\nQuality: 85/100 | Updated: 2026-05-19\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import (\n    LetsPlot,\n    aes,\n    coord_fixed,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_contourf,\n    geom_path,\n    geom_point,\n    geom_text,\n    ggplot,\n    ggsize,\n    labs,\n    layer_tooltips,\n    scale_fill_viridis,\n    scale_size,\n    theme,\n    theme_minimal,\n)\nfrom lets_plot.export import ggsave\nfrom scipy.stats import gaussian_kde\n\n\nLetsPlot.setup_html()\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nRULE = \"rgba(26,26,23,0.12)\" if THEME == \"light\" else \"rgba(240,239,232,0.12)\"\n\n# Data — synthetic California seismic events clustered around major fault lines\nnp.random.seed(42)\nn_points = 600\n\nla_lat = np.random.normal(34.05, 0.6, n_points // 3)\nla_lon = np.random.normal(-118.25, 0.6, n_points // 3)\nla_magnitude = np.random.exponential(2.0, n_points // 3) + 1\n\nsf_lat = np.random.normal(37.77, 0.4, n_points // 3)\nsf_lon = np.random.normal(-122.42, 0.4, n_points // 3)\nsf_magnitude = np.random.exponential(2.2, n_points // 3) + 1.2\n\ncv_lat = np.random.uniform(35.5, 37.5, n_points // 3)\ncv_lon = np.random.uniform(-121.5, -119.5, n_points // 3)\ncv_magnitude = np.random.exponential(1.5, n_points // 3) + 0.8\n\nlatitude = np.concatenate([la_lat, sf_lat, cv_lat])\nlongitude = np.concatenate([la_lon, sf_lon, cv_lon])\nmagnitude = np.concatenate([la_magnitude, sf_magnitude, cv_magnitude])\n\ndf = pd.DataFrame({\"latitude\": latitude, \"longitude\": longitude, \"magnitude\": magnitude})\n\n# KDE on a regular grid for the continuous density heatmap\nlon_min, lon_max = -124, -116\nlat_min, lat_max = 32, 40\nn_grid = 80\n\nlon_grid = np.linspace(lon_min, lon_max, n_grid)\nlat_grid = np.linspace(lat_min, lat_max, n_grid)\nlon_mesh, lat_mesh = np.meshgrid(lon_grid, lat_grid)\n\npositions = np.vstack([longitude, latitude])\nkernel = gaussian_kde(positions, bw_method=0.15)\ngrid_positions = np.vstack([lon_mesh.ravel(), lat_mesh.ravel()])\ndensity = kernel(grid_positions).reshape(lon_mesh.shape)\n\ndf_grid = pd.DataFrame({\"longitude\": lon_mesh.flatten(), \"latitude\": lat_mesh.flatten(), \"density\": density.flatten()})\n\n# City labels for geographic context\ncity_labels = pd.DataFrame({\"lon\": [-122.42, -118.25], \"lat\": [38.2, 34.5], \"city\": [\"San Francisco\", \"Los Angeles\"]})\n\n# Simplified California coastline for geographic context\nca_coast = pd.DataFrame(\n    {\n        \"lon\": [-124.4, -124.2, -123.7, -122.4, -121.8, -120.6, -120.2, -118.5, -117.1, -117.0, -116.1],\n        \"lat\": [40.3, 39.5, 38.9, 37.8, 37.0, 35.5, 34.5, 34.0, 32.5, 33.0, 32.7],\n    }\n)\n\n# Plot\nplot = (\n    ggplot()\n    + geom_contourf(aes(x=\"longitude\", y=\"latitude\", z=\"density\", fill=\"..level..\"), data=df_grid, bins=12, alpha=0.85)\n    + geom_path(aes(x=\"lon\", y=\"lat\"), data=ca_coast, color=INK_SOFT, size=1.5)\n    + geom_text(aes(x=\"lon\", y=\"lat\", label=\"city\"), data=city_labels, color=INK, size=13, hjust=0.5, fontface=\"bold\")\n    + geom_point(\n        aes(x=\"longitude\", y=\"latitude\", size=\"magnitude\"),\n        data=df,\n        color=\"#4467A3\",\n        alpha=0.5,\n        shape=21,\n        fill=\"#AE3030\",\n        stroke=0.5,\n        tooltips=layer_tooltips()\n        .line(\"Lat: @latitude{.2f}\")\n        .line(\"Lon: @longitude{.2f}\")\n        .line(\"Magnitude: @magnitude{.1f}\"),\n    )\n    + scale_fill_viridis(name=\"Event\\nDensity\")\n    + scale_size(range=[2, 10], name=\"Magnitude\")\n    + labs(\n        x=\"Longitude\",\n        y=\"Latitude\",\n        title=\"Seismic Activity Density · heatmap-geographic · python · letsplot · anyplot.ai\",\n    )\n    + coord_fixed(ratio=1.0, xlim=[lon_min, lon_max], ylim=[lat_min, lat_max])\n    + ggsize(1200, 1200)\n    + theme_minimal()\n    + theme(\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        plot_title=element_text(size=24, face=\"bold\", color=INK),\n        axis_title=element_text(size=20, color=INK),\n        axis_text=element_text(size=16, color=INK_SOFT),\n        legend_title=element_text(size=16, color=INK),\n        legend_text=element_text(size=16, color=INK_SOFT),\n        legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n        panel_grid_major=element_line(color=RULE, size=0.5),\n        panel_grid_minor=element_blank(),\n    )\n)\n\n# Save\nggsave(plot, f\"plot-{THEME}.png\", path=\".\", scale=3)\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}