entropy25 commited on
Commit
23e5b5c
·
verified ·
1 Parent(s): 46ef3c3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -15
app.py CHANGED
@@ -532,6 +532,8 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
532
  doc = SimpleDocTemplate(buffer, pagesize=A4, rightMargin=50, leftMargin=50, topMargin=50, bottomMargin=50)
533
  elements = []
534
  styles = getSampleStyleSheet()
 
 
535
  title_style = ParagraphStyle(
536
  'CustomTitle',
537
  parent=styles['Heading1'],
@@ -540,6 +542,7 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
540
  alignment=1,
541
  textColor=colors.darkblue
542
  )
 
543
  subtitle_style = ParagraphStyle(
544
  'CustomSubtitle',
545
  parent=styles['Heading2'],
@@ -547,18 +550,22 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
547
  spaceAfter=20,
548
  textColor=colors.darkblue
549
  )
550
- ai_style = ParagraphStyle(
551
- 'AIStyle',
 
552
  parent=styles['Normal'],
553
  fontSize=11,
554
  spaceAfter=12,
555
  leftIndent=20,
556
  textColor=colors.darkgreen
557
  )
 
 
558
  elements.append(Spacer(1, 100))
559
- elements.append(Paragraph("Production Monitor with AI Insights", title_style))
560
  elements.append(Paragraph("Comprehensive Production Analysis Report", styles['Heading3']))
561
  elements.append(Spacer(1, 50))
 
562
  report_info = f"""
563
  <para alignment="center">
564
  <b>Nilsen Service &amp; Consulting AS</b><br/>
@@ -570,10 +577,14 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
570
  """
571
  elements.append(Paragraph(report_info, styles['Normal']))
572
  elements.append(PageBreak())
 
 
573
  elements.append(Paragraph("Executive Summary", subtitle_style))
 
574
  total_production = stats['_total_']['total']
575
  work_days = stats['_total_']['work_days']
576
  daily_avg = stats['_total_']['daily_avg']
 
577
  exec_summary = f"""
578
  <para>
579
  This report analyzes production data spanning <b>{work_days} working days</b>.
@@ -589,6 +600,8 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
589
  """
590
  elements.append(Paragraph(exec_summary, styles['Normal']))
591
  elements.append(Spacer(1, 20))
 
 
592
  elements.append(Paragraph("Production Summary", styles['Heading3']))
593
  summary_data = [['Material Type', 'Total (kg)', 'Share (%)', 'Daily Avg (kg)']]
594
  for material, info in stats.items():
@@ -599,6 +612,7 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
599
  f"{info['percentage']:.1f}%",
600
  f"{info['daily_avg']:,.0f}"
601
  ])
 
602
  summary_table = Table(summary_data, colWidths=[2*inch, 1.5*inch, 1*inch, 1.5*inch])
603
  summary_table.setStyle(TableStyle([
604
  ('BACKGROUND', (0, 0), (-1, 0), colors.darkblue),
@@ -610,11 +624,15 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
610
  ]))
611
  elements.append(summary_table)
612
  elements.append(PageBreak())
 
 
613
  elements.append(Paragraph("Production Analysis Charts", subtitle_style))
 
614
  try:
615
  charts = create_pdf_charts(df, stats)
616
  except:
617
  charts = {}
 
618
  charts_added = False
619
  chart_insights = {
620
  'pie': "Material distribution shows production allocation across different materials. Balanced distribution indicates diversified production capabilities.",
@@ -622,6 +640,7 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
622
  'bar': "Material comparison highlights performance differences and production capacities. Top performers indicate optimization opportunities.",
623
  'shift': "Shift analysis reveals operational efficiency differences between day and night operations. Balance indicates effective resource utilization."
624
  }
 
625
  for chart_type, chart_title in [
626
  ('pie', "Production Distribution"),
627
  ('trend', "Production Trend"),
@@ -634,11 +653,12 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
634
  elements.append(Paragraph(chart_title, styles['Heading3']))
635
  elements.append(Image(chart_path, width=6*inch, height=3*inch))
636
  insight_text = f"<i>Analysis: {chart_insights.get(chart_type, 'Chart analysis not available.')}</i>"
637
- elements.append(Paragraph(insight_text, ai_style))
638
  elements.append(Spacer(1, 20))
639
  charts_added = True
640
  except Exception as e:
641
  pass
 
642
  if not charts_added:
643
  elements.append(Paragraph("Charts Generation Failed", styles['Heading3']))
644
  elements.append(Paragraph("Production Data Summary:", styles['Normal']))
@@ -647,8 +667,12 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
647
  summary_text = f"• {material.replace('_', ' ').title()}: {info['total']:,.0f} kg ({info['percentage']:.1f}%)"
648
  elements.append(Paragraph(summary_text, styles['Normal']))
649
  elements.append(Spacer(1, 20))
 
650
  elements.append(PageBreak())
 
 
651
  elements.append(Paragraph("Quality Control Analysis", subtitle_style))
 
652
  quality_data = [['Material', 'Outliers', 'Normal Range (kg)', 'Status']]
653
  for material, info in outliers.items():
654
  if info['count'] == 0:
@@ -657,12 +681,14 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
657
  status = "MONITOR"
658
  else:
659
  status = "ATTENTION"
 
660
  quality_data.append([
661
  material.replace('_', ' ').title(),
662
  str(info['count']),
663
  info['range'],
664
  status
665
  ])
 
666
  quality_table = Table(quality_data, colWidths=[2*inch, 1*inch, 2*inch, 1.5*inch])
667
  quality_table.setStyle(TableStyle([
668
  ('BACKGROUND', (0, 0), (-1, 0), colors.darkred),
@@ -673,15 +699,18 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
673
  ('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.lightgrey])
674
  ]))
675
  elements.append(quality_table)
 
 
676
  if model:
677
  elements.append(PageBreak())
678
- elements.append(Paragraph("AI Intelligent Analysis", subtitle_style))
679
  try:
680
- ai_analysis = generate_ai_summary(model, df, stats, outliers)
681
  except:
682
- ai_analysis = "AI analysis temporarily unavailable."
683
- ai_paragraphs = ai_analysis.split('\n\n')
684
- for paragraph in ai_paragraphs:
 
685
  if paragraph.strip():
686
  formatted_text = paragraph.replace('**', '<b>', 1).replace('**', '</b>', 1) \
687
  .replace('•', ' •') \
@@ -690,8 +719,10 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
690
  elements.append(Spacer(1, 8))
691
  else:
692
  elements.append(PageBreak())
693
- elements.append(Paragraph("AI Analysis", subtitle_style))
694
- elements.append(Paragraph("AI analysis unavailable - Google API key not configured. Please set the GOOGLE_API_KEY environment variable or configure it in Streamlit secrets to enable intelligent insights.", styles['Normal']))
 
 
695
  elements.append(Spacer(1, 30))
696
  footer_text = f"""
697
  <para alignment="center">
@@ -701,6 +732,7 @@ def create_enhanced_pdf_report(df, stats, outliers, model=None):
701
  </para>
702
  """
703
  elements.append(Paragraph(footer_text, styles['Normal']))
 
704
  doc.build(elements)
705
  buffer.seek(0)
706
  return buffer
@@ -719,33 +751,39 @@ def create_csv_export(df, stats):
719
  ])
720
  return summary_df
721
 
 
722
  def add_export_section(df, stats, outliers, model):
723
  st.markdown('<div class="section-header">📄 Export Reports</div>', unsafe_allow_html=True)
 
724
  if 'export_ready' not in st.session_state:
725
  st.session_state.export_ready = False
726
  if 'pdf_buffer' not in st.session_state:
727
  st.session_state.pdf_buffer = None
728
  if 'csv_data' not in st.session_state:
729
  st.session_state.csv_data = None
 
730
  col1, col2, col3 = st.columns(3)
 
731
  with col1:
732
- if st.button("Generate PDF Report with AI", key="generate_pdf_btn", type="primary"):
733
  try:
734
- with st.spinner("Generating PDF with AI analysis..."):
735
  st.session_state.pdf_buffer = create_enhanced_pdf_report(df, stats, outliers, model)
736
  st.session_state.export_ready = True
737
- st.success("✅ PDF report with AI analysis generated successfully!")
738
  except Exception as e:
739
  st.error(f"❌ PDF generation failed: {str(e)}")
740
  st.session_state.export_ready = False
 
741
  if st.session_state.export_ready and st.session_state.pdf_buffer:
742
  st.download_button(
743
  label="💾 Download PDF Report",
744
  data=st.session_state.pdf_buffer,
745
- file_name=f"production_report_ai_{datetime.now().strftime('%Y%m%d_%H%M')}.pdf",
746
  mime="application/pdf",
747
  key="download_pdf_btn"
748
  )
 
749
  with col2:
750
  if st.button("Generate CSV Summary", key="generate_csv_btn", type="primary"):
751
  try:
@@ -753,6 +791,7 @@ def add_export_section(df, stats, outliers, model):
753
  st.success("✅ CSV summary generated successfully!")
754
  except Exception as e:
755
  st.error(f"❌ CSV generation failed: {str(e)}")
 
756
  if st.session_state.csv_data is not None:
757
  csv_string = st.session_state.csv_data.to_csv(index=False)
758
  st.download_button(
@@ -762,6 +801,7 @@ def add_export_section(df, stats, outliers, model):
762
  mime="text/csv",
763
  key="download_csv_btn"
764
  )
 
765
  with col3:
766
  csv_string = df.to_csv(index=False)
767
  st.download_button(
 
532
  doc = SimpleDocTemplate(buffer, pagesize=A4, rightMargin=50, leftMargin=50, topMargin=50, bottomMargin=50)
533
  elements = []
534
  styles = getSampleStyleSheet()
535
+
536
+ # Custom styles
537
  title_style = ParagraphStyle(
538
  'CustomTitle',
539
  parent=styles['Heading1'],
 
542
  alignment=1,
543
  textColor=colors.darkblue
544
  )
545
+
546
  subtitle_style = ParagraphStyle(
547
  'CustomSubtitle',
548
  parent=styles['Heading2'],
 
550
  spaceAfter=20,
551
  textColor=colors.darkblue
552
  )
553
+
554
+ analysis_style = ParagraphStyle(
555
+ 'AnalysisStyle',
556
  parent=styles['Normal'],
557
  fontSize=11,
558
  spaceAfter=12,
559
  leftIndent=20,
560
  textColor=colors.darkgreen
561
  )
562
+
563
+ # Title page
564
  elements.append(Spacer(1, 100))
565
+ elements.append(Paragraph("Production Monitor Dashboard", title_style))
566
  elements.append(Paragraph("Comprehensive Production Analysis Report", styles['Heading3']))
567
  elements.append(Spacer(1, 50))
568
+
569
  report_info = f"""
570
  <para alignment="center">
571
  <b>Nilsen Service &amp; Consulting AS</b><br/>
 
577
  """
578
  elements.append(Paragraph(report_info, styles['Normal']))
579
  elements.append(PageBreak())
580
+
581
+ # Executive Summary
582
  elements.append(Paragraph("Executive Summary", subtitle_style))
583
+
584
  total_production = stats['_total_']['total']
585
  work_days = stats['_total_']['work_days']
586
  daily_avg = stats['_total_']['daily_avg']
587
+
588
  exec_summary = f"""
589
  <para>
590
  This report analyzes production data spanning <b>{work_days} working days</b>.
 
600
  """
601
  elements.append(Paragraph(exec_summary, styles['Normal']))
602
  elements.append(Spacer(1, 20))
603
+
604
+ # Production Summary Table
605
  elements.append(Paragraph("Production Summary", styles['Heading3']))
606
  summary_data = [['Material Type', 'Total (kg)', 'Share (%)', 'Daily Avg (kg)']]
607
  for material, info in stats.items():
 
612
  f"{info['percentage']:.1f}%",
613
  f"{info['daily_avg']:,.0f}"
614
  ])
615
+
616
  summary_table = Table(summary_data, colWidths=[2*inch, 1.5*inch, 1*inch, 1.5*inch])
617
  summary_table.setStyle(TableStyle([
618
  ('BACKGROUND', (0, 0), (-1, 0), colors.darkblue),
 
624
  ]))
625
  elements.append(summary_table)
626
  elements.append(PageBreak())
627
+
628
+ # Charts Section
629
  elements.append(Paragraph("Production Analysis Charts", subtitle_style))
630
+
631
  try:
632
  charts = create_pdf_charts(df, stats)
633
  except:
634
  charts = {}
635
+
636
  charts_added = False
637
  chart_insights = {
638
  'pie': "Material distribution shows production allocation across different materials. Balanced distribution indicates diversified production capabilities.",
 
640
  'bar': "Material comparison highlights performance differences and production capacities. Top performers indicate optimization opportunities.",
641
  'shift': "Shift analysis reveals operational efficiency differences between day and night operations. Balance indicates effective resource utilization."
642
  }
643
+
644
  for chart_type, chart_title in [
645
  ('pie', "Production Distribution"),
646
  ('trend', "Production Trend"),
 
653
  elements.append(Paragraph(chart_title, styles['Heading3']))
654
  elements.append(Image(chart_path, width=6*inch, height=3*inch))
655
  insight_text = f"<i>Analysis: {chart_insights.get(chart_type, 'Chart analysis not available.')}</i>"
656
+ elements.append(Paragraph(insight_text, analysis_style))
657
  elements.append(Spacer(1, 20))
658
  charts_added = True
659
  except Exception as e:
660
  pass
661
+
662
  if not charts_added:
663
  elements.append(Paragraph("Charts Generation Failed", styles['Heading3']))
664
  elements.append(Paragraph("Production Data Summary:", styles['Normal']))
 
667
  summary_text = f"• {material.replace('_', ' ').title()}: {info['total']:,.0f} kg ({info['percentage']:.1f}%)"
668
  elements.append(Paragraph(summary_text, styles['Normal']))
669
  elements.append(Spacer(1, 20))
670
+
671
  elements.append(PageBreak())
672
+
673
+ # Quality Control Analysis
674
  elements.append(Paragraph("Quality Control Analysis", subtitle_style))
675
+
676
  quality_data = [['Material', 'Outliers', 'Normal Range (kg)', 'Status']]
677
  for material, info in outliers.items():
678
  if info['count'] == 0:
 
681
  status = "MONITOR"
682
  else:
683
  status = "ATTENTION"
684
+
685
  quality_data.append([
686
  material.replace('_', ' ').title(),
687
  str(info['count']),
688
  info['range'],
689
  status
690
  ])
691
+
692
  quality_table = Table(quality_data, colWidths=[2*inch, 1*inch, 2*inch, 1.5*inch])
693
  quality_table.setStyle(TableStyle([
694
  ('BACKGROUND', (0, 0), (-1, 0), colors.darkred),
 
699
  ('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.lightgrey])
700
  ]))
701
  elements.append(quality_table)
702
+
703
+ # Intelligent Analysis (if model available)
704
  if model:
705
  elements.append(PageBreak())
706
+ elements.append(Paragraph("Intelligent Analysis", subtitle_style))
707
  try:
708
+ analysis = generate_ai_summary(model, df, stats, outliers)
709
  except:
710
+ analysis = "Intelligent analysis temporarily unavailable."
711
+
712
+ analysis_paragraphs = analysis.split('\n\n')
713
+ for paragraph in analysis_paragraphs:
714
  if paragraph.strip():
715
  formatted_text = paragraph.replace('**', '<b>', 1).replace('**', '</b>', 1) \
716
  .replace('•', ' •') \
 
719
  elements.append(Spacer(1, 8))
720
  else:
721
  elements.append(PageBreak())
722
+ elements.append(Paragraph("Advanced Analysis", subtitle_style))
723
+ elements.append(Paragraph("Advanced analysis features unavailable - Google API key not configured. Please set the GOOGLE_API_KEY environment variable or configure it in Streamlit secrets to enable intelligent insights.", styles['Normal']))
724
+
725
+ # Footer
726
  elements.append(Spacer(1, 30))
727
  footer_text = f"""
728
  <para alignment="center">
 
732
  </para>
733
  """
734
  elements.append(Paragraph(footer_text, styles['Normal']))
735
+
736
  doc.build(elements)
737
  buffer.seek(0)
738
  return buffer
 
751
  ])
752
  return summary_df
753
 
754
+
755
  def add_export_section(df, stats, outliers, model):
756
  st.markdown('<div class="section-header">📄 Export Reports</div>', unsafe_allow_html=True)
757
+
758
  if 'export_ready' not in st.session_state:
759
  st.session_state.export_ready = False
760
  if 'pdf_buffer' not in st.session_state:
761
  st.session_state.pdf_buffer = None
762
  if 'csv_data' not in st.session_state:
763
  st.session_state.csv_data = None
764
+
765
  col1, col2, col3 = st.columns(3)
766
+
767
  with col1:
768
+ if st.button("Generate PDF Report", key="generate_pdf_btn", type="primary"):
769
  try:
770
+ with st.spinner("Generating comprehensive PDF report..."):
771
  st.session_state.pdf_buffer = create_enhanced_pdf_report(df, stats, outliers, model)
772
  st.session_state.export_ready = True
773
+ st.success("✅ PDF report generated successfully!")
774
  except Exception as e:
775
  st.error(f"❌ PDF generation failed: {str(e)}")
776
  st.session_state.export_ready = False
777
+
778
  if st.session_state.export_ready and st.session_state.pdf_buffer:
779
  st.download_button(
780
  label="💾 Download PDF Report",
781
  data=st.session_state.pdf_buffer,
782
+ file_name=f"production_report_{datetime.now().strftime('%Y%m%d_%H%M')}.pdf",
783
  mime="application/pdf",
784
  key="download_pdf_btn"
785
  )
786
+
787
  with col2:
788
  if st.button("Generate CSV Summary", key="generate_csv_btn", type="primary"):
789
  try:
 
791
  st.success("✅ CSV summary generated successfully!")
792
  except Exception as e:
793
  st.error(f"❌ CSV generation failed: {str(e)}")
794
+
795
  if st.session_state.csv_data is not None:
796
  csv_string = st.session_state.csv_data.to_csv(index=False)
797
  st.download_button(
 
801
  mime="text/csv",
802
  key="download_csv_btn"
803
  )
804
+
805
  with col3:
806
  csv_string = df.to_csv(index=False)
807
  st.download_button(