Update app.py
Browse files
app.py
CHANGED
|
@@ -324,6 +324,9 @@ 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 |
temp_dir = tempfile.gettempdir()
|
| 328 |
filepath = os.path.join(temp_dir, filename)
|
| 329 |
|
|
@@ -335,19 +338,12 @@ def save_plotly_as_image(fig, filename):
|
|
| 335 |
margin=dict(t=50, b=40, l=40, r=40)
|
| 336 |
)
|
| 337 |
|
| 338 |
-
|
| 339 |
-
try:
|
| 340 |
-
pio.write_image(fig, filepath, format='png', width=800, height=400, scale=2, engine='kaleido')
|
| 341 |
-
except:
|
| 342 |
-
try:
|
| 343 |
-
pio.write_image(fig, filepath, format='png', width=800, height=400, scale=1, engine='orca')
|
| 344 |
-
except:
|
| 345 |
-
# Fallback: save as HTML and convert manually
|
| 346 |
-
html_path = filepath.replace('.png', '.html')
|
| 347 |
-
fig.write_html(html_path)
|
| 348 |
-
return None # Skip image if conversion fails
|
| 349 |
-
|
| 350 |
return filepath if os.path.exists(filepath) else None
|
|
|
|
|
|
|
|
|
|
|
|
|
| 351 |
except Exception as e:
|
| 352 |
st.warning(f"Chart save error: {e}")
|
| 353 |
return None
|
|
@@ -481,32 +477,57 @@ def create_enhanced_pdf_report(df, stats, outliers):
|
|
| 481 |
# Generate and add charts
|
| 482 |
elements.append(Paragraph("Production Analysis Charts", subtitle_style))
|
| 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(Spacer(1, 20))
|
| 511 |
|
| 512 |
# Quality Analysis
|
|
|
|
| 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 |
margin=dict(t=50, b=40, l=40, r=40)
|
| 339 |
)
|
| 340 |
|
| 341 |
+
pio.write_image(fig, filepath, format='png', width=800, height=400, scale=2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 342 |
return filepath if os.path.exists(filepath) else None
|
| 343 |
+
|
| 344 |
+
except ImportError:
|
| 345 |
+
st.warning("📸 Kaleido not installed. Charts will not appear in PDF. Run: pip install kaleido")
|
| 346 |
+
return None
|
| 347 |
except Exception as e:
|
| 348 |
st.warning(f"Chart save error: {e}")
|
| 349 |
return None
|
|
|
|
| 477 |
# Generate and add charts
|
| 478 |
elements.append(Paragraph("Production Analysis Charts", subtitle_style))
|
| 479 |
|
| 480 |
+
try:
|
| 481 |
+
# Check if kaleido is available
|
| 482 |
+
import kaleido
|
| 483 |
+
|
| 484 |
+
with st.spinner("Generating charts for PDF..."):
|
| 485 |
+
charts = create_pdf_charts(df, stats)
|
| 486 |
+
|
| 487 |
+
# Add charts to PDF
|
| 488 |
+
charts_added = False
|
| 489 |
+
|
| 490 |
+
if charts.get('pie') and charts['pie'] and os.path.exists(charts['pie']):
|
| 491 |
+
elements.append(Paragraph("Production Distribution", styles['Heading3']))
|
| 492 |
+
elements.append(Image(charts['pie'], width=6*inch, height=3*inch))
|
| 493 |
+
elements.append(Spacer(1, 20))
|
| 494 |
+
charts_added = True
|
| 495 |
+
|
| 496 |
+
if charts.get('trend') and charts['trend'] and os.path.exists(charts['trend']):
|
| 497 |
+
elements.append(Paragraph("Production Trend", styles['Heading3']))
|
| 498 |
+
elements.append(Image(charts['trend'], width=6*inch, height=3*inch))
|
| 499 |
+
elements.append(Spacer(1, 20))
|
| 500 |
+
charts_added = True
|
| 501 |
+
|
| 502 |
+
if charts.get('bar') and charts['bar'] and os.path.exists(charts['bar']):
|
| 503 |
+
elements.append(Paragraph("Material Comparison", styles['Heading3']))
|
| 504 |
+
elements.append(Image(charts['bar'], width=6*inch, height=3*inch))
|
| 505 |
+
elements.append(Spacer(1, 20))
|
| 506 |
+
charts_added = True
|
| 507 |
+
|
| 508 |
+
if charts.get('shift') and charts['shift'] and os.path.exists(charts['shift']):
|
| 509 |
+
elements.append(Paragraph("Shift Analysis", styles['Heading3']))
|
| 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 data summary instead
|
| 526 |
+
elements.append(Paragraph("Production Summary (Text Format):", styles['Normal']))
|
| 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}%)"
|
| 530 |
+
elements.append(Paragraph(summary_text, styles['Normal']))
|
| 531 |
elements.append(Spacer(1, 20))
|
| 532 |
|
| 533 |
# Quality Analysis
|