Skip to main content
Glama
imagery.py5.33 kB
""" Satellite imagery search and retrieval tools. """ import asyncio from datetime import datetime, timedelta from typing import Optional, Literal import structlog from geosight.config import settings from geosight.tools.geocoding import resolve_location from geosight.services.sentinel_hub import SentinelHubService from geosight.services.planetary_computer import PlanetaryComputerService logger = structlog.get_logger(__name__) async def search_imagery( start_date: str, end_date: str, latitude: Optional[float] = None, longitude: Optional[float] = None, location_name: Optional[str] = None, max_cloud_cover: float = 20.0, data_source: Literal["sentinel-2", "landsat-8", "landsat-9", "sentinel-1"] = "sentinel-2", ) -> dict: """ Search for available satellite imagery for a given location and date range. Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format latitude: Center latitude longitude: Center longitude location_name: Location name to geocode max_cloud_cover: Maximum cloud cover percentage data_source: Satellite data source Returns: Dictionary with search results and imagery metadata """ try: # Resolve location lat, lon, display_name = await resolve_location( location_name=location_name, latitude=latitude, longitude=longitude, ) logger.info( "searching_imagery", location=display_name, lat=lat, lon=lon, start_date=start_date, end_date=end_date, data_source=data_source, ) # Parse dates start = datetime.strptime(start_date, "%Y-%m-%d") end = datetime.strptime(end_date, "%Y-%m-%d") # Use Planetary Computer for free data access service = PlanetaryComputerService() results = await service.search_imagery( latitude=lat, longitude=lon, start_date=start, end_date=end, collection=data_source, max_cloud_cover=max_cloud_cover, ) # Format results if not results["items"]: return { "summary": f"🔍 **No imagery found**\n" f" Location: {display_name}\n" f" Date range: {start_date} to {end_date}\n" f" Data source: {data_source}\n" f" Max cloud cover: {max_cloud_cover}%\n\n" f"💡 Try expanding the date range or increasing max cloud cover.", "items": [], "statistics": { "total_results": 0, "date_range_days": (end - start).days, }, } # Build summary items = results["items"] summary_lines = [ f"🛰️ **Found {len(items)} image{'s' if len(items) != 1 else ''}**", f" 📍 Location: {display_name}", f" 📅 Date range: {start_date} to {end_date}", f" 🛰️ Data source: {data_source.upper()}", f" ☁️ Max cloud cover: {max_cloud_cover}%", "", "**Available imagery:**", ] for i, item in enumerate(items[:10], 1): # Show top 10 date = item.get("datetime", "Unknown date") cloud = item.get("cloud_cover", "N/A") cloud_str = f"{cloud:.1f}%" if isinstance(cloud, (int, float)) else cloud summary_lines.append(f" {i}. {date} | Cloud: {cloud_str}") if len(items) > 10: summary_lines.append(f" ... and {len(items) - 10} more") # Calculate statistics cloud_covers = [ item["cloud_cover"] for item in items if isinstance(item.get("cloud_cover"), (int, float)) ] stats = { "total_results": len(items), "date_range_days": (end - start).days, "avg_cloud_cover_pct": sum(cloud_covers) / len(cloud_covers) if cloud_covers else None, "min_cloud_cover_pct": min(cloud_covers) if cloud_covers else None, "best_image_date": items[0].get("datetime") if items else None, } return { "summary": "\n".join(summary_lines), "items": items, "location": { "name": display_name, "latitude": lat, "longitude": lon, }, "search_params": { "start_date": start_date, "end_date": end_date, "data_source": data_source, "max_cloud_cover": max_cloud_cover, }, "statistics": stats, } except ValueError as e: return { "summary": f"❌ **Error:** {str(e)}", "error": str(e), } except Exception as e: logger.error("imagery_search_error", error=str(e), exc_info=True) return { "summary": f"❌ **Search failed:** {str(e)}", "error": str(e), }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/armaasinghn/geosight-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server