import matplotlib.pyplot as plt import numpy as np from reportlab.lib.pagesizes import letter from reportlab.pdfgen import canvas from reportlab.lib.utils import ImageReader import os from datetime import datetime def create_percentage_circle(percentage, title): """ Create a circular progress bar for percentage visualization. """ fig, ax = plt.subplots(figsize=(4, 4)) ax.set_aspect("equal") circle = plt.Circle((0.5, 0.5), 0.4, color="lightgray") ax.add_patch(circle) theta = np.linspace(0, 360 * (percentage / 100), 100) x = 0.5 + 0.4 * np.cos(np.radians(theta)) y = 0.5 + 0.4 * np.sin(np.radians(theta)) ax.plot(x, y, color="blue", linewidth=20) ax.text(0.5, 0.5, f"{percentage:.1f}%", ha="center", va="center", fontsize=20) ax.set_title(title, fontsize=12) ax.axis("off") output_path = f"screenshots/circle_{int(percentage)}_{int(np.random.randint(1000))}.png" plt.savefig(output_path, bbox_inches="tight") plt.close() return output_path def generate_pdf_report(summary, screenshots, output_path): """ Generate a PDF report using reportlab with summary and embedded screenshots. """ c = canvas.Canvas(output_path, pagesize=letter) width, height = letter # Title c.setFont("Helvetica", 16) c.drawString(100, height - 50, "Road Safety Analysis Report") c.setFont("Helvetica", 12) c.drawString(100, height - 70, f"Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") # Summary c.setFont("Helvetica", 12) c.drawString(100, height - 100, "Analysis Summary:") y = height - 120 for line in summary.split('\n'): if line.strip(): c.drawString(120, y, line.strip()) y -= 20 if y < 100: # New page if running out of space c.showPage() y = height - 50 # Screenshots if screenshots: c.showPage() c.setFont("Helvetica", 12) c.drawString(100, height - 50, "Incident Screenshots:") y = height - 70 for i, screenshot in enumerate(screenshots[:5]): # Limit to 5 images if os.path.exists(screenshot): img = ImageReader(screenshot) img_width = 200 img_height = img_width * (img.getSize()[1] / img.getSize()[0]) if y - img_height < 50: c.showPage() y = height - 50 c.drawImage(screenshot, 100, y - img_height, width=img_width, height=img_height) c.drawString(100, y - img_height - 20, f"Incident Frame {i+1}") y -= img_height + 30 c.save()