RathodHarish commited on
Commit
e434d29
·
verified ·
1 Parent(s): 89dfd1d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -127
app.py CHANGED
@@ -1,150 +1,89 @@
1
  import gradio as gr
2
  import pandas as pd
3
  import matplotlib.pyplot as plt
 
4
  import io
5
- from datetime import datetime
6
- from reportlab.lib.pagesizes import letter
7
- from reportlab.pdfgen import canvas
8
 
9
- REQUIRED_COLUMNS = ['DeviceID', 'Lab', 'Type', 'Timestamp', 'Status', 'UsageCount']
10
 
11
- # ----------------------------
12
- # Load Logs Safely
13
- # ----------------------------
14
- def load_logs(file_obj):
15
  try:
16
- if file_obj is not None:
17
- df = pd.read_csv(file_obj.name)
18
- df.columns = df.columns.str.strip() # remove whitespace around column names
19
- if not all(col in df.columns for col in REQUIRED_COLUMNS):
20
- raise ValueError(f"CSV must contain columns: {', '.join(REQUIRED_COLUMNS)}")
21
- df['Timestamp'] = pd.to_datetime(df['Timestamp'], errors='coerce')
22
- df.dropna(subset=['Timestamp'], inplace=True)
23
- else:
24
- df = pd.DataFrame({
25
- 'DeviceID': ['D001', 'D002', 'D003'],
26
- 'Lab': ['Lab A', 'Lab B', 'Lab A'],
27
- 'Type': ['UV', 'Weight', 'Cell'],
28
- 'Timestamp': [pd.Timestamp('2025-06-01 09:00:00'),
29
- pd.Timestamp('2025-06-01 10:00:00'),
30
- pd.Timestamp('2025-06-01 11:00:00')],
31
- 'Status': ['OK', 'DOWN', 'OK'],
32
- 'UsageCount': [120, 85, 100]
33
- })
34
- return df
35
  except Exception as e:
36
- raise ValueError(f"Failed to load CSV: {e}")
37
 
38
- # ----------------------------
39
- # Summarize Log Data
40
- # ----------------------------
41
- def summarize_logs(df, selected_lab, selected_type):
 
42
  if selected_lab != "All":
43
- df = df[df['Lab'] == selected_lab]
44
  if selected_type != "All":
45
- df = df[df['Type'] == selected_type]
46
- summary = df.groupby(['Lab', 'Type'])['Status'].value_counts().unstack().fillna(0)
47
- return summary
48
-
49
- # ----------------------------
50
- # Generate Chart
51
- # ----------------------------
52
- def generate_chart(df, selected_lab, selected_type):
53
- summary = summarize_logs(df, selected_lab, selected_type)
54
- fig, ax = plt.subplots(figsize=(8, 4))
55
- summary.plot(kind='bar', stacked=True, ax=ax)
56
- ax.set_title("Device Uptime/Downtime Summary")
57
- ax.set_ylabel("Count")
58
- ax.set_xlabel("Lab + Device Type")
59
- ax.legend(title="Status")
60
- fig.tight_layout()
61
- return fig
62
-
63
- # ----------------------------
64
- # Export PDF using ReportLab
65
- # ----------------------------
66
- def export_pdf(df, selected_lab, selected_type):
67
- summary = summarize_logs(df, selected_lab, selected_type)
68
- buffer = io.BytesIO()
69
- pdf = canvas.Canvas(buffer, pagesize=letter)
70
- width, height = letter
71
-
72
- pdf.setFont("Helvetica-Bold", 14)
73
- pdf.drawCentredString(width / 2, height - 40, "LabOps Dashboard Summary Report")
74
- pdf.setFont("Helvetica", 10)
75
- pdf.drawCentredString(width / 2, height - 60, f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
76
-
77
- y = height - 100
78
- pdf.setFont("Helvetica-Bold", 10)
79
- pdf.drawString(50, y, "Lab")
80
- pdf.drawString(150, y, "Device Type")
81
- pdf.drawString(300, y, "OK")
82
- pdf.drawString(350, y, "DOWN")
83
- y -= 20
84
- pdf.setFont("Helvetica", 10)
85
-
86
- for (lab, dev_type), row in summary.iterrows():
87
- pdf.drawString(50, y, str(lab))
88
- pdf.drawString(150, y, str(dev_type))
89
- pdf.drawString(300, y, str(int(row.get('OK', 0))))
90
- pdf.drawString(350, y, str(int(row.get('DOWN', 0))))
91
- y -= 20
92
- if y < 50:
93
- pdf.showPage()
94
- y = height - 50
95
-
96
- pdf.save()
97
- buffer.seek(0)
98
- return ("LabOps_Summary.pdf", buffer.read())
99
 
100
- # ----------------------------
101
- # Dashboard Interface Logic
102
- # ----------------------------
103
- def update_ui(file_obj):
104
- try:
105
- df = load_logs(file_obj)
106
- labs = ["All"] + sorted(df['Lab'].unique().tolist())
107
- types = ["All"] + sorted(df['Type'].unique().tolist())
108
- return df, gr.Dropdown.update(choices=labs, value="All"), gr.Dropdown.update(choices=types, value="All"), gr.Textbox.update(visible=False)
109
- except Exception as e:
110
- return None, gr.Dropdown.update(choices=[], value=None), gr.Dropdown.update(choices=[], value=None), gr.Textbox.update(value=f"❌ Error: {e}", visible=True)
111
 
112
- def dashboard(df, selected_lab, selected_type):
113
- try:
114
- return generate_chart(df, selected_lab, selected_type)
115
- except Exception as e:
116
- return gr.update(visible=True), gr.Textbox.update(value=f"❌ Error: {e}", visible=True)
117
 
118
- def generate_pdf_button(df, selected_lab, selected_type):
119
- try:
120
- filename, pdf_bytes = export_pdf(df, selected_lab, selected_type)
121
- return gr.File.update(value=(filename, pdf_bytes), visible=True), gr.Textbox.update(visible=False)
122
- except Exception as e:
123
- return gr.File.update(visible=False), gr.Textbox.update(value=f"❌ Error: {e}", visible=True)
124
 
125
- # ----------------------------
126
- # Gradio Interface
127
- # ----------------------------
128
  with gr.Blocks() as demo:
129
- gr.Markdown("## 🖊️ LabOps Dashboard with Filters")
130
- gr.Markdown("Upload lab device logs, filter by Lab and Equipment Type, visualize uptime/downtime & generate PDF reports.")
131
-
132
- df_state = gr.State()
133
 
134
  with gr.Row():
135
- file_input = gr.File(label="Upload Log CSV", file_types=[".csv"])
 
 
136
  lab_dropdown = gr.Dropdown(label="Select Lab", choices=["All"])
137
  type_dropdown = gr.Dropdown(label="Select Equipment Type", choices=["All"])
138
 
139
- plot_output = gr.Plot()
140
- error_output = gr.Textbox(visible=False, label="Errors")
141
- download_button = gr.Button("Download PDF Summary")
142
- download_file = gr.File(label="Download PDF", visible=False)
143
 
144
- file_input.change(fn=update_ui, inputs=file_input, outputs=[df_state, lab_dropdown, type_dropdown, error_output])
145
- lab_dropdown.change(fn=dashboard, inputs=[df_state, lab_dropdown, type_dropdown], outputs=plot_output)
146
- type_dropdown.change(fn=dashboard, inputs=[df_state, lab_dropdown, type_dropdown], outputs=plot_output)
147
- download_button.click(fn=generate_pdf_button, inputs=[df_state, lab_dropdown, type_dropdown], outputs=[download_file, error_output])
148
 
149
- if __name__ == '__main__':
150
- demo.launch()
 
1
  import gradio as gr
2
  import pandas as pd
3
  import matplotlib.pyplot as plt
4
+ from fpdf import FPDF
5
  import io
 
 
 
6
 
7
+ df = pd.DataFrame()
8
 
9
+ def upload_csv(file):
10
+ global df
 
 
11
  try:
12
+ df = pd.read_csv(file.name)
13
+ required_columns = {'DeviceID', 'Lab', 'Type', 'Timestamp', 'Status', 'UsageCount'}
14
+ if not required_columns.issubset(df.columns):
15
+ return None, "CSV must contain columns: " + ", ".join(required_columns)
16
+ labs = ['All'] + sorted(df['Lab'].dropna().unique().tolist())
17
+ types = ['All'] + sorted(df['Type'].dropna().unique().tolist())
18
+ return (labs, types), ""
 
 
 
 
 
 
 
 
 
 
 
 
19
  except Exception as e:
20
+ return None, f"Failed to load CSV: {str(e)}"
21
 
22
+ def filter_and_plot(selected_lab, selected_type):
23
+ global df
24
+ if df.empty:
25
+ return None
26
+ filtered_df = df.copy()
27
  if selected_lab != "All":
28
+ filtered_df = filtered_df[filtered_df["Lab"] == selected_lab]
29
  if selected_type != "All":
30
+ filtered_df = filtered_df[filtered_df["Type"] == selected_type]
31
+
32
+ # Prepare plot
33
+ plt.figure(figsize=(8, 4))
34
+ status_counts = filtered_df["Status"].value_counts()
35
+ status_counts.plot(kind="bar", color=["green", "red"])
36
+ plt.title("Status Counts")
37
+ plt.xlabel("Status")
38
+ plt.ylabel("Count")
39
+
40
+ buf = io.BytesIO()
41
+ plt.savefig(buf, format="png")
42
+ buf.seek(0)
43
+ return buf
44
+
45
+ def download_pdf(selected_lab, selected_type):
46
+ global df
47
+ if df.empty:
48
+ return None
49
+ filtered_df = df.copy()
50
+ if selected_lab != "All":
51
+ filtered_df = filtered_df[filtered_df["Lab"] == selected_lab]
52
+ if selected_type != "All":
53
+ filtered_df = filtered_df[filtered_df["Type"] == selected_type]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
+ pdf = FPDF()
56
+ pdf.add_page()
57
+ pdf.set_font("Arial", size=12)
58
+ pdf.cell(200, 10, txt="LabOps Summary Report", ln=True, align='C')
59
+ pdf.ln(10)
 
 
 
 
 
 
60
 
61
+ for index, row in filtered_df.iterrows():
62
+ line = f"{row['Timestamp']} | {row['DeviceID']} | {row['Lab']} | {row['Type']} | {row['Status']} | {row['UsageCount']}"
63
+ pdf.multi_cell(0, 10, txt=line)
 
 
64
 
65
+ output = io.BytesIO()
66
+ pdf.output(output)
67
+ output.seek(0)
68
+ return output
 
 
69
 
 
 
 
70
  with gr.Blocks() as demo:
71
+ gr.Markdown("🧪 **LabOps Dashboard with Filters**\nUpload lab device logs, filter by Lab and Equipment Type, visualize uptime/downtime & generate PDF reports.")
 
 
 
72
 
73
  with gr.Row():
74
+ csv_input = gr.File(label="Upload Log CSV", file_types=[".csv"])
75
+
76
+ with gr.Row():
77
  lab_dropdown = gr.Dropdown(label="Select Lab", choices=["All"])
78
  type_dropdown = gr.Dropdown(label="Select Equipment Type", choices=["All"])
79
 
80
+ plot_output = gr.Image(label="Plot")
81
+ download_btn = gr.Button("Download PDF Summary")
82
+ error_box = gr.Textbox(visible=False)
 
83
 
84
+ csv_input.change(fn=upload_csv, inputs=csv_input, outputs=[(lab_dropdown, type_dropdown), error_box])
85
+ lab_dropdown.change(fn=filter_and_plot, inputs=[lab_dropdown, type_dropdown], outputs=plot_output)
86
+ type_dropdown.change(fn=filter_and_plot, inputs=[lab_dropdown, type_dropdown], outputs=plot_output)
87
+ download_btn.click(fn=download_pdf, inputs=[lab_dropdown, type_dropdown], outputs=gr.File())
88
 
89
+ demo.launch()