Skip to main content
Glama
reports.py8.95 kB
""" Report generation tool for comprehensive analysis. """ from datetime import datetime from typing import Optional, List, Literal import structlog from geosight.tools.geocoding import resolve_location from geosight.tools.indices import calculate_ndvi, calculate_ndwi from geosight.tools.classification import detect_land_cover from geosight.tools.change_detection import detect_changes logger = structlog.get_logger(__name__) async def generate_report( start_date: str, end_date: str, latitude: Optional[float] = None, longitude: Optional[float] = None, location_name: Optional[str] = None, radius_km: float = 10.0, analyses: Optional[List[str]] = None, output_format: Literal["pdf", "html", "markdown"] = "markdown", report_title: Optional[str] = None, ) -> dict: """Generate comprehensive analysis report.""" try: lat, lon, display_name = await resolve_location( location_name=location_name, latitude=latitude, longitude=longitude, ) if analyses is None: analyses = ["ndvi", "land_cover"] logger.info( "generating_report", location=display_name, analyses=analyses, ) title = report_title or f"Satellite Analysis Report: {display_name}" # Run requested analyses results = {} if "ndvi" in analyses: results["ndvi"] = await calculate_ndvi( start_date=start_date, end_date=end_date, latitude=lat, longitude=lon, radius_km=radius_km, ) if "ndwi" in analyses: results["ndwi"] = await calculate_ndwi( start_date=start_date, end_date=end_date, latitude=lat, longitude=lon, radius_km=radius_km, ) if "land_cover" in analyses: results["land_cover"] = await detect_land_cover( date=end_date, latitude=lat, longitude=lon, radius_km=radius_km, ) if "change_detection" in analyses: results["change_detection"] = await detect_changes( date_before=start_date, date_after=end_date, latitude=lat, longitude=lon, radius_km=radius_km, ) # Generate report content if output_format == "markdown": report_content = generate_markdown_report( title, display_name, lat, lon, start_date, end_date, radius_km, results ) elif output_format == "html": report_content = generate_html_report( title, display_name, lat, lon, start_date, end_date, radius_km, results ) else: report_content = generate_markdown_report( title, display_name, lat, lon, start_date, end_date, radius_km, results ) summary = f"""📄 **Report Generated Successfully** 📍 **Location:** {display_name} 📅 **Period:** {start_date} to {end_date} 📐 **Area:** {(radius_km * 2) ** 2:.1f} km² 📊 **Analyses included:** {', '.join(analyses)} 📝 **Format:** {output_format.upper()} The report includes detailed analysis results with visualizations. """ return { "summary": summary, "report_content": report_content, "format": output_format, "title": title, "analyses_completed": list(results.keys()), "statistics": { "location": display_name, "latitude": lat, "longitude": lon, "start_date": start_date, "end_date": end_date, "radius_km": radius_km, }, } except ValueError as e: return {"summary": f"❌ **Error:** {str(e)}", "error": str(e)} except Exception as e: logger.error("report_generation_error", error=str(e), exc_info=True) return {"summary": f"❌ **Report generation failed:** {str(e)}", "error": str(e)} def generate_markdown_report( title: str, location: str, lat: float, lon: float, start_date: str, end_date: str, radius_km: float, results: dict, ) -> str: """Generate Markdown report.""" sections = [ f"# {title}", "", f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", "", "## Executive Summary", "", f"This report presents satellite imagery analysis for **{location}** ", f"covering the period from {start_date} to {end_date}.", "", "## Study Area", "", f"- **Location:** {location}", f"- **Coordinates:** {lat:.4f}°N, {lon:.4f}°E", f"- **Analysis Area:** {(radius_km * 2):.1f} km × {(radius_km * 2):.1f} km ({(radius_km * 2) ** 2:.1f} km²)", f"- **Date Range:** {start_date} to {end_date}", "", ] if "ndvi" in results: ndvi = results["ndvi"] stats = ndvi.get("statistics", {}) sections.extend([ "## Vegetation Analysis (NDVI)", "", "The Normalized Difference Vegetation Index (NDVI) measures vegetation health and density.", "", f"- **Mean NDVI:** {stats.get('mean_ndvi', 'N/A'):.3f}" if isinstance(stats.get('mean_ndvi'), (int, float)) else "- **Mean NDVI:** N/A", f"- **Dense Vegetation:** {stats.get('dense_vegetation_pct', 0):.1f}%", f"- **Moderate Vegetation:** {stats.get('moderate_vegetation_pct', 0):.1f}%", f"- **Sparse Vegetation:** {stats.get('sparse_vegetation_pct', 0):.1f}%", "", ]) if "ndwi" in results: ndwi = results["ndwi"] stats = ndwi.get("statistics", {}) sections.extend([ "## Water Analysis (NDWI)", "", "The Normalized Difference Water Index (NDWI) identifies water bodies and moisture.", "", f"- **Water Coverage:** {stats.get('water_coverage_pct', 0):.1f}%", f"- **Water Area:** {stats.get('water_area_km2', 0):.2f} km²", "", ]) if "land_cover" in results: lc = results["land_cover"] stats = lc.get("statistics", {}) classes = stats.get("class_percentages", {}) sections.extend([ "## Land Cover Classification", "", "Machine learning classification of land cover types:", "", ]) for class_name, pct in sorted(classes.items(), key=lambda x: -x[1]): if pct > 0.5: sections.append(f"- **{class_name}:** {pct:.1f}%") sections.append("") if "change_detection" in results: cd = results["change_detection"] stats = cd.get("statistics", {}) sections.extend([ "## Change Detection", "", f"Analysis of changes between {start_date} and {end_date}:", "", f"- **Changed Area:** {stats.get('changed_area_km2', 0):.2f} km²", f"- **Change Percentage:** {stats.get('change_percentage', 0):.1f}%", "", ]) sections.extend([ "## Methodology", "", "This analysis uses Sentinel-2 satellite imagery processed through the GeoSight platform.", "Machine learning models are applied for land cover classification and object detection.", "", "## Disclaimer", "", "This report is generated automatically and should be verified with ground truth data.", "", "---", f"*Report generated by GeoSight MCP Server v1.0.0*", ]) return "\n".join(sections) def generate_html_report( title: str, location: str, lat: float, lon: float, start_date: str, end_date: str, radius_km: float, results: dict, ) -> str: """Generate HTML report.""" markdown_content = generate_markdown_report( title, location, lat, lon, start_date, end_date, radius_km, results ) # Simple markdown to HTML conversion html_content = f"""<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>{title}</title> <style> body {{ font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }} h1 {{ color: #2c3e50; border-bottom: 2px solid #3498db; }} h2 {{ color: #34495e; margin-top: 30px; }} ul {{ list-style-type: disc; }} .stats {{ background: #f8f9fa; padding: 15px; border-radius: 5px; }} </style> </head> <body> <pre>{markdown_content}</pre> </body> </html>""" return html_content

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