Update app.py
Browse files
app.py
CHANGED
|
@@ -324,9 +324,6 @@ def query_ai(model, stats, question, df=None):
|
|
| 324 |
def save_plotly_as_image(fig, filename):
|
| 325 |
"""Convert Plotly figure to PNG for PDF"""
|
| 326 |
try:
|
| 327 |
-
# Check if kaleido is available
|
| 328 |
-
import kaleido
|
| 329 |
-
|
| 330 |
temp_dir = tempfile.gettempdir()
|
| 331 |
filepath = os.path.join(temp_dir, filename)
|
| 332 |
|
|
@@ -338,44 +335,66 @@ def save_plotly_as_image(fig, filename):
|
|
| 338 |
margin=dict(t=50, b=40, l=40, r=40)
|
| 339 |
)
|
| 340 |
|
| 341 |
-
|
| 342 |
-
|
| 343 |
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 347 |
except Exception as e:
|
| 348 |
-
|
|
|
|
| 349 |
return None
|
| 350 |
|
| 351 |
def create_pdf_charts(df, stats):
|
| 352 |
"""Generate charts for PDF report"""
|
| 353 |
charts = {}
|
| 354 |
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 379 |
|
| 380 |
return charts
|
| 381 |
|
|
@@ -477,53 +496,40 @@ def create_enhanced_pdf_report(df, stats, outliers):
|
|
| 477 |
# Generate and add charts
|
| 478 |
elements.append(Paragraph("Production Analysis Charts", subtitle_style))
|
| 479 |
|
| 480 |
-
|
| 481 |
-
|
| 482 |
-
|
| 483 |
-
|
| 484 |
-
|
| 485 |
-
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
|
| 490 |
-
|
| 491 |
-
|
| 492 |
-
|
| 493 |
-
|
| 494 |
-
|
| 495 |
-
|
| 496 |
-
|
| 497 |
-
|
| 498 |
-
|
| 499 |
-
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
|
| 505 |
-
|
| 506 |
-
|
| 507 |
-
|
| 508 |
-
|
| 509 |
-
|
| 510 |
-
elements.append(Image(charts['shift'], width=6*inch, height=3*inch))
|
| 511 |
-
elements.append(Spacer(1, 20))
|
| 512 |
-
charts_added = True
|
| 513 |
-
|
| 514 |
-
if not charts_added:
|
| 515 |
-
elements.append(Paragraph("Charts could not be generated. Please install kaleido: pip install kaleido", styles['Normal']))
|
| 516 |
-
elements.append(Spacer(1, 20))
|
| 517 |
-
|
| 518 |
-
except ImportError:
|
| 519 |
-
# Kaleido not available - add text summary instead
|
| 520 |
-
elements.append(Paragraph("Charts Not Available", styles['Heading3']))
|
| 521 |
-
elements.append(Paragraph("To enable charts in PDF reports, please install kaleido:", styles['Normal']))
|
| 522 |
-
elements.append(Paragraph("<b>pip install kaleido</b>", styles['Normal']))
|
| 523 |
elements.append(Spacer(1, 10))
|
| 524 |
|
| 525 |
-
# Add text-based
|
| 526 |
-
elements.append(Paragraph("Production
|
| 527 |
for material, info in stats.items():
|
| 528 |
if material != '_total_':
|
| 529 |
summary_text = f"• {material.replace('_', ' ').title()}: {info['total']:,.0f} kg ({info['percentage']:.1f}%)"
|
|
|
|
| 324 |
def save_plotly_as_image(fig, filename):
|
| 325 |
"""Convert Plotly figure to PNG for PDF"""
|
| 326 |
try:
|
|
|
|
|
|
|
|
|
|
| 327 |
temp_dir = tempfile.gettempdir()
|
| 328 |
filepath = os.path.join(temp_dir, filename)
|
| 329 |
|
|
|
|
| 335 |
margin=dict(t=50, b=40, l=40, r=40)
|
| 336 |
)
|
| 337 |
|
| 338 |
+
# Debug info
|
| 339 |
+
print(f"Attempting to save chart to: {filepath}")
|
| 340 |
|
| 341 |
+
# Use kaleido explicitly
|
| 342 |
+
pio.write_image(fig, filepath, format='png', width=800, height=400, scale=2, engine='kaleido')
|
| 343 |
+
|
| 344 |
+
# Check if file was created
|
| 345 |
+
if os.path.exists(filepath):
|
| 346 |
+
file_size = os.path.getsize(filepath)
|
| 347 |
+
print(f"Chart saved successfully: {filepath} ({file_size} bytes)")
|
| 348 |
+
return filepath
|
| 349 |
+
else:
|
| 350 |
+
print("Chart file was not created")
|
| 351 |
+
return None
|
| 352 |
+
|
| 353 |
except Exception as e:
|
| 354 |
+
print(f"Chart save error: {str(e)}")
|
| 355 |
+
st.error(f"Chart save error: {str(e)}")
|
| 356 |
return None
|
| 357 |
|
| 358 |
def create_pdf_charts(df, stats):
|
| 359 |
"""Generate charts for PDF report"""
|
| 360 |
charts = {}
|
| 361 |
|
| 362 |
+
try:
|
| 363 |
+
# Production distribution pie chart
|
| 364 |
+
materials = [k for k in stats.keys() if k != '_total_']
|
| 365 |
+
values = [stats[mat]['total'] for mat in materials]
|
| 366 |
+
labels = [mat.replace('_', ' ').title() for mat in materials]
|
| 367 |
+
|
| 368 |
+
if len(materials) > 0 and len(values) > 0:
|
| 369 |
+
fig_pie = px.pie(values=values, names=labels, title="Production Distribution by Material")
|
| 370 |
+
charts['pie'] = save_plotly_as_image(fig_pie, "distribution.png")
|
| 371 |
+
|
| 372 |
+
# Daily production trend
|
| 373 |
+
if len(df) > 0:
|
| 374 |
+
daily_data = df.groupby('date')['weight_kg'].sum().reset_index()
|
| 375 |
+
if len(daily_data) > 0:
|
| 376 |
+
fig_trend = px.line(daily_data, x='date', y='weight_kg', title="Daily Production Trend")
|
| 377 |
+
fig_trend.update_layout(xaxis_title="Date", yaxis_title="Weight (kg)")
|
| 378 |
+
charts['trend'] = save_plotly_as_image(fig_trend, "trend.png")
|
| 379 |
+
|
| 380 |
+
# Material comparison bar chart
|
| 381 |
+
if len(materials) > 0 and len(values) > 0:
|
| 382 |
+
fig_bar = px.bar(x=labels, y=values, title="Production by Material Type")
|
| 383 |
+
fig_bar.update_layout(xaxis_title="Material Type", yaxis_title="Weight (kg)")
|
| 384 |
+
charts['bar'] = save_plotly_as_image(fig_bar, "materials.png")
|
| 385 |
+
|
| 386 |
+
# Shift analysis if available
|
| 387 |
+
if 'shift' in df.columns and len(df) > 0:
|
| 388 |
+
shift_data = df.groupby('shift')['weight_kg'].sum().reset_index()
|
| 389 |
+
if len(shift_data) > 0 and shift_data['weight_kg'].sum() > 0:
|
| 390 |
+
fig_shift = px.pie(shift_data, values='weight_kg', names='shift', title="Production by Shift")
|
| 391 |
+
charts['shift'] = save_plotly_as_image(fig_shift, "shifts.png")
|
| 392 |
+
|
| 393 |
+
print(f"Charts created: {list(charts.keys())}")
|
| 394 |
+
|
| 395 |
+
except Exception as e:
|
| 396 |
+
print(f"Error creating charts: {str(e)}")
|
| 397 |
+
st.error(f"Error creating charts: {str(e)}")
|
| 398 |
|
| 399 |
return charts
|
| 400 |
|
|
|
|
| 496 |
# Generate and add charts
|
| 497 |
elements.append(Paragraph("Production Analysis Charts", subtitle_style))
|
| 498 |
|
| 499 |
+
with st.spinner("Generating charts for PDF..."):
|
| 500 |
+
charts = create_pdf_charts(df, stats)
|
| 501 |
+
|
| 502 |
+
# Add charts to PDF with better error checking
|
| 503 |
+
charts_added = False
|
| 504 |
+
|
| 505 |
+
for chart_type, chart_titles in [
|
| 506 |
+
('pie', "Production Distribution"),
|
| 507 |
+
('trend', "Production Trend"),
|
| 508 |
+
('bar', "Material Comparison"),
|
| 509 |
+
('shift', "Shift Analysis")
|
| 510 |
+
]:
|
| 511 |
+
chart_path = charts.get(chart_type)
|
| 512 |
+
if chart_path and os.path.exists(chart_path):
|
| 513 |
+
try:
|
| 514 |
+
elements.append(Paragraph(chart_titles, styles['Heading3']))
|
| 515 |
+
elements.append(Image(chart_path, width=6*inch, height=3*inch))
|
| 516 |
+
elements.append(Spacer(1, 20))
|
| 517 |
+
charts_added = True
|
| 518 |
+
print(f"Added chart: {chart_type}")
|
| 519 |
+
except Exception as e:
|
| 520 |
+
print(f"Error adding chart {chart_type}: {str(e)}")
|
| 521 |
+
st.warning(f"Could not add {chart_type} chart to PDF: {str(e)}")
|
| 522 |
+
|
| 523 |
+
if not charts_added:
|
| 524 |
+
elements.append(Paragraph("Charts Generation Failed", styles['Heading3']))
|
| 525 |
+
elements.append(Paragraph("Possible issues:", styles['Normal']))
|
| 526 |
+
elements.append(Paragraph("1. Kaleido installation problem", styles['Normal']))
|
| 527 |
+
elements.append(Paragraph("2. File permissions issue", styles['Normal']))
|
| 528 |
+
elements.append(Paragraph("3. Data format problem", styles['Normal']))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 529 |
elements.append(Spacer(1, 10))
|
| 530 |
|
| 531 |
+
# Add text-based summary instead
|
| 532 |
+
elements.append(Paragraph("Production Data Summary:", styles['Normal']))
|
| 533 |
for material, info in stats.items():
|
| 534 |
if material != '_total_':
|
| 535 |
summary_text = f"• {material.replace('_', ' ').title()}: {info['total']:,.0f} kg ({info['percentage']:.1f}%)"
|