|
import os
|
|
import pandas as pd
|
|
from reportlab.pdfgen import canvas
|
|
from reportlab.lib.pagesizes import letter
|
|
import tempfile
|
|
import matplotlib.pyplot as plt
|
|
from reportlab.lib import colors
|
|
from Damage_calculation import DamageCalculator
|
|
from reportlab.platypus import Table, TableStyle
|
|
|
|
class PDFReportGenerator:
|
|
def __init__(self, output_csv, output_folder, pdf_path):
|
|
self.output_csv = output_csv
|
|
self.damage_folder = os.path.join(output_folder, 'damage/labels')
|
|
self.parts_folder = os.path.join(output_folder, 'parts/labels')
|
|
self.pdf_path = pdf_path
|
|
self.calculator = DamageCalculator()
|
|
|
|
def create_pie_chart(self, part_class, damage_summary):
|
|
part_damage = damage_summary.get(part_class, {})
|
|
if not part_damage:
|
|
return None
|
|
|
|
damage_labels = list(part_damage['damage_types'].keys()) + ['Undamaged']
|
|
damage_values = list(part_damage['damage_types'].values()) + [part_damage['undamaged']]
|
|
|
|
fig, ax = plt.subplots(figsize=(6, 6))
|
|
ax.pie(damage_values, labels=damage_labels, autopct='%1.1f%%', startangle=140, textprops={'fontsize': 14})
|
|
ax.axis('equal')
|
|
|
|
img_temp_path = tempfile.mktemp(suffix=".png")
|
|
plt.savefig(img_temp_path, bbox_inches='tight')
|
|
plt.close(fig)
|
|
return img_temp_path
|
|
|
|
def add_table_to_pdf(self, pdf, dataframe, x_position, y_position):
|
|
|
|
dataframe = dataframe.fillna('-')
|
|
|
|
data = [dataframe.columns.to_list()] + dataframe.values.tolist()
|
|
table = Table(data)
|
|
|
|
|
|
style = TableStyle([
|
|
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
|
|
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
|
|
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
|
|
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
|
|
('FONTSIZE', (0, 0), (-1, 0), 12),
|
|
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
|
|
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
|
|
('GRID', (0, 0), (-1, -1), 1, colors.black)
|
|
])
|
|
|
|
table.setStyle(style)
|
|
|
|
|
|
table.wrapOn(pdf, x_position, y_position)
|
|
table.drawOn(pdf, x_position, y_position)
|
|
|
|
|
|
def generate_report(self):
|
|
df = pd.read_csv(self.output_csv)
|
|
car_parts = df['Car Parts'].unique()
|
|
|
|
|
|
damage_summary = {}
|
|
|
|
|
|
damage_files = sorted(os.listdir(self.damage_folder))
|
|
parts_files = sorted(os.listdir(self.parts_folder))
|
|
|
|
|
|
for damage_file, parts_file in zip(damage_files, parts_files):
|
|
damage_path = os.path.join(self.damage_folder, damage_file)
|
|
parts_path = os.path.join(self.parts_folder, parts_file)
|
|
|
|
damage_classes, damage_polygons = self.calculator.parse_coordinates(damage_path)
|
|
part_classes, part_polygons = self.calculator.parse_coordinates(parts_path)
|
|
|
|
damage_polygons = list(zip(damage_classes, damage_polygons))
|
|
part_polygons = list(zip(part_classes, part_polygons))
|
|
|
|
part_summary = self.calculator.summarize_damage_by_part(damage_polygons, part_polygons)
|
|
for part, summary in part_summary.items():
|
|
if part not in damage_summary:
|
|
damage_summary[part] = summary
|
|
else:
|
|
for damage_type, percentage in summary['damage_types'].items():
|
|
if damage_type not in damage_summary[part]['damage_types']:
|
|
damage_summary[part]['damage_types'][damage_type] = 0
|
|
damage_summary[part]['damage_types'][damage_type] += percentage
|
|
damage_summary[part]['undamaged'] += summary['undamaged']
|
|
|
|
pdf = canvas.Canvas(self.pdf_path, pagesize=letter)
|
|
pdf.setTitle("Car Damage Estimation Report")
|
|
|
|
width, height = letter
|
|
y_position = height - 40
|
|
|
|
for part_class in car_parts:
|
|
if part_class == 'Total':
|
|
continue
|
|
|
|
pdf.setFont("Helvetica-Bold", 12)
|
|
pdf.drawString(30, y_position, f'Damage Report for {part_class}')
|
|
y_position -= 20
|
|
|
|
pie_chart_path = self.create_pie_chart(part_class, damage_summary)
|
|
if pie_chart_path:
|
|
pdf.drawImage(pie_chart_path, 50, y_position - 300, width=275, height=275)
|
|
y_position -= 320
|
|
|
|
|
|
os.remove(pie_chart_path)
|
|
|
|
if y_position < 100:
|
|
pdf.showPage()
|
|
y_position = height - 40
|
|
|
|
|
|
y_position -= 40
|
|
pdf.setFont("Helvetica-Bold", 14)
|
|
pdf.drawString(50, y_position, "Cost Breakdown Table")
|
|
y_position -= 200
|
|
|
|
|
|
self.add_table_to_pdf(pdf, df, 30, y_position-100)
|
|
|
|
pdf.save()
|
|
|