Auto-update: Fri Nov 15 13:14:54 PST 2024

This commit is contained in:
sanj 2024-11-15 13:14:54 -08:00
parent 4c51798a78
commit 3cfebd7fff

View file

@ -8,9 +8,8 @@ from fastapi.responses import HTMLResponse, JSONResponse
import random import random
from pathlib import Path from pathlib import Path
import traceback import traceback
import matplotlib.pyplot as plt from staticmap import StaticMap, CircleMarker
import contextily as ctx from io import BytesIO
import numpy as np
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import Union, List from typing import Union, List
import folium import folium
@ -125,11 +124,12 @@ async def get_last_location() -> Optional[Location]:
async def generate_and_save_heatmap( async def generate_and_save_heatmap(
start_date: Union[str, int, datetime], start_date: Union[str, int, datetime],
end_date: Optional[Union[str, int, datetime]] = None, end_date: Optional[Union[str, int, datetime]] = None,
output_path: Optional[Path] = None output_path: Optional[Path] = None
) -> Path: ) -> Path:
""" """
Generate a heatmap for the given date range and save it as a PNG file. Generate a heatmap for the given date range and save it as a PNG file.
@ -139,7 +139,6 @@ Generate a heatmap for the given date range and save it as a PNG file.
:return: The path where the PNG file was saved :return: The path where the PNG file was saved
""" """
try: try:
start_date = await dt(start_date) start_date = await dt(start_date)
if end_date: if end_date:
end_date = await dt(end_date) end_date = await dt(end_date)
@ -150,53 +149,22 @@ Generate a heatmap for the given date range and save it as a PNG file.
if not locations: if not locations:
raise ValueError("No locations found for the given date range") raise ValueError("No locations found for the given date range")
lats = np.array([loc.latitude for loc in locations]) # Create map
lons = np.array([loc.longitude for loc in locations]) m = StaticMap(640, 360, url_template='https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png')
# Calculate bounds with 5% buffer # Add markers with heat effect
lat_range = max(lats) - min(lats) for loc in locations:
lon_range = max(lons) - min(lons) marker = CircleMarker((loc.longitude, loc.latitude), 'red', 12)
buffer = max(lat_range, lon_range) * 0.05 m.add_marker(marker)
# Render the image
image = m.render()
# Enforce minimum zoom
MIN_RANGE = 0.05
lat_range = max(lat_range, MIN_RANGE)
lon_range = max(lon_range, MIN_RANGE)
# Create figure with fixed size
fig, ax = plt.subplots(figsize=(6.4, 3.6), dpi=100)
# Set map extent
ax.set_xlim(min(lons) - buffer, max(lons) + buffer)
ax.set_ylim(min(lats) - buffer, max(lats) + buffer)
# Create heatmap overlay
heatmap = ax.hexbin(
lons, lats,
gridsize=25,
cmap='hot',
alpha=0.6,
zorder=2
)
# Add dark basemap
ctx.add_basemap(
ax,
source=ctx.providers.CartoDB.DarkMatter,
zoom='auto'
)
# Remove axes and margins
ax.set_axis_off()
plt.subplots_adjust(left=0, right=1, top=1, bottom=0)
if output_path is None: if output_path is None:
output_path, relative_path = assemble_journal_path(end_date, filename="map", extension=".png", no_timestamp=True) output_path, relative_path = assemble_journal_path(end_date, filename="map", extension=".png", no_timestamp=True)
plt.savefig(output_path, bbox_inches='tight', pad_inches=0, dpi=100) # Save the image
plt.close() image.save(output_path)
l.info(f"Heatmap saved as PNG: {output_path}")
return output_path return output_path
except Exception as e: except Exception as e:
@ -205,6 +173,7 @@ Generate a heatmap for the given date range and save it as a PNG file.
async def generate_map(start_date: datetime, end_date: datetime, max_points: int): async def generate_map(start_date: datetime, end_date: datetime, max_points: int):
locations = await fetch_locations(start_date, end_date) locations = await fetch_locations(start_date, end_date)
if not locations: if not locations: