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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -71
app.py CHANGED
@@ -14,14 +14,13 @@ REQUIRED_COLUMNS = ['DeviceID', 'Lab', 'Type', 'Timestamp', 'Status', 'UsageCoun
14
  def load_logs(file_obj):
15
  try:
16
  if file_obj is not None:
17
- # file_obj is a NamedTemporaryFile, get file path to read with pandas directly
18
  df = pd.read_csv(file_obj.name)
 
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
- # Default sample data
25
  df = pd.DataFrame({
26
  'DeviceID': ['D001', 'D002', 'D003'],
27
  'Lab': ['Lab A', 'Lab B', 'Lab A'],
@@ -36,36 +35,22 @@ def load_logs(file_obj):
36
  except Exception as e:
37
  raise ValueError(f"Failed to load CSV: {e}")
38
 
39
- # ----------------------------
40
- # Filter dataframe by Lab and Type
41
- # ----------------------------
42
- def filter_data(df, lab, dev_type):
43
- if lab != "All":
44
- df = df[df['Lab'] == lab]
45
- if dev_type != "All":
46
- df = df[df['Type'] == dev_type]
47
- return df
48
-
49
  # ----------------------------
50
  # Summarize Log Data
51
  # ----------------------------
52
- def summarize_logs(df):
53
- if df.empty:
54
- return pd.DataFrame(columns=['OK', 'DOWN'])
 
 
55
  summary = df.groupby(['Lab', 'Type'])['Status'].value_counts().unstack().fillna(0)
56
  return summary
57
 
58
  # ----------------------------
59
  # Generate Chart
60
  # ----------------------------
61
- def generate_chart(df, lab, dev_type):
62
- filtered_df = filter_data(df, lab, dev_type)
63
- summary = summarize_logs(filtered_df)
64
- if summary.empty:
65
- fig, ax = plt.subplots()
66
- ax.text(0.5, 0.5, "No data for selected filters", ha='center', va='center')
67
- ax.axis('off')
68
- return fig
69
  fig, ax = plt.subplots(figsize=(8, 4))
70
  summary.plot(kind='bar', stacked=True, ax=ax)
71
  ax.set_title("Device Uptime/Downtime Summary")
@@ -78,9 +63,8 @@ def generate_chart(df, lab, dev_type):
78
  # ----------------------------
79
  # Export PDF using ReportLab
80
  # ----------------------------
81
- def export_pdf(df, lab, dev_type):
82
- filtered_df = filter_data(df, lab, dev_type)
83
- summary = summarize_logs(filtered_df)
84
  buffer = io.BytesIO()
85
  pdf = canvas.Canvas(buffer, pagesize=letter)
86
  width, height = letter
@@ -89,9 +73,8 @@ def export_pdf(df, lab, dev_type):
89
  pdf.drawCentredString(width / 2, height - 40, "LabOps Dashboard Summary Report")
90
  pdf.setFont("Helvetica", 10)
91
  pdf.drawCentredString(width / 2, height - 60, f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
92
- pdf.drawCentredString(width / 2, height - 80, f"Filters - Lab: {lab}, Type: {dev_type}")
93
 
94
- y = height - 110
95
  pdf.setFont("Helvetica-Bold", 10)
96
  pdf.drawString(50, y, "Lab")
97
  pdf.drawString(150, y, "Device Type")
@@ -100,9 +83,9 @@ def export_pdf(df, lab, dev_type):
100
  y -= 20
101
  pdf.setFont("Helvetica", 10)
102
 
103
- for (lab_name, dev_type_name), row in summary.iterrows():
104
- pdf.drawString(50, y, str(lab_name))
105
- pdf.drawString(150, y, str(dev_type_name))
106
  pdf.drawString(300, y, str(int(row.get('OK', 0))))
107
  pdf.drawString(350, y, str(int(row.get('DOWN', 0))))
108
  y -= 20
@@ -115,61 +98,53 @@ def export_pdf(df, lab, dev_type):
115
  return ("LabOps_Summary.pdf", buffer.read())
116
 
117
  # ----------------------------
118
- # UI Functions
119
  # ----------------------------
 
 
 
 
 
 
 
 
120
 
121
- def get_unique_labs_types(df):
122
- labs = ["All"] + sorted(df['Lab'].unique().tolist())
123
- types = ["All"] + sorted(df['Type'].unique().tolist())
124
- return labs, types
125
-
126
- def on_file_load(file_obj):
127
- df = load_logs(file_obj)
128
- labs, types = get_unique_labs_types(df)
129
- fig = generate_chart(df, "All", "All")
130
- return fig, gr.Dropdown.update(choices=labs, value="All"), gr.Dropdown.update(choices=types, value="All"), ""
131
-
132
- def on_filter_change(file_obj, lab, dev_type):
133
- df = load_logs(file_obj)
134
- fig = generate_chart(df, lab, dev_type)
135
- return fig
136
 
137
- def on_generate_pdf(file_obj, lab, dev_type):
138
- df = load_logs(file_obj)
139
  try:
140
- filename, pdf_bytes = export_pdf(df, lab, dev_type)
141
- return gr.File.update(value=(filename, pdf_bytes), visible=True), ""
142
  except Exception as e:
143
- return gr.File.update(visible=False), f"❌ Error generating PDF: {e}"
144
 
145
  # ----------------------------
146
  # Gradio Interface
147
  # ----------------------------
148
  with gr.Blocks() as demo:
149
- gr.Markdown("## 🧪 LabOps Dashboard with Filters")
150
  gr.Markdown("Upload lab device logs, filter by Lab and Equipment Type, visualize uptime/downtime & generate PDF reports.")
151
 
 
 
152
  with gr.Row():
153
  file_input = gr.File(label="Upload Log CSV", file_types=[".csv"])
154
- with gr.Row():
155
- lab_dropdown = gr.Dropdown(label="Select Lab", choices=["All"], value="All")
156
- type_dropdown = gr.Dropdown(label="Select Equipment Type", choices=["All"], value="All")
157
 
158
  plot_output = gr.Plot()
159
- error_output = gr.Textbox(visible=False, interactive=False, label="Errors", lines=1)
160
-
161
- with gr.Row():
162
- download_button = gr.Button("Download PDF Summary")
163
- download_file = gr.File(label="Download PDF", visible=False)
164
-
165
- # Load file -> update dropdowns & plot
166
- file_input.change(fn=on_file_load, inputs=file_input, outputs=[plot_output, lab_dropdown, type_dropdown, error_output])
167
-
168
- # When filters change -> update plot only
169
- lab_dropdown.change(fn=on_filter_change, inputs=[file_input, lab_dropdown, type_dropdown], outputs=plot_output)
170
- type_dropdown.change(fn=on_filter_change, inputs=[file_input, lab_dropdown, type_dropdown], outputs=plot_output)
171
 
172
- # Generate PDF button
173
- download_button.click(fn=on_generate_pdf, inputs=[file_input, lab_dropdown, type_dropdown], outputs=[download_file, error_output])
 
 
174
 
175
- demo.launch()
 
 
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'],
 
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")
 
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
 
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")
 
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
 
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()