Dineshpopuri commited on
Commit
818baee
·
verified ·
1 Parent(s): 5844b87

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +157 -97
app.py CHANGED
@@ -1,117 +1,177 @@
1
  import gradio as gr
2
- import json
3
  import pandas as pd
 
 
 
4
 
5
- def create_contact_from_can(cands_from_trigger):
6
- """
7
- Process a list of candidate dictionaries to create contact records.
 
 
 
8
 
9
- Args:
10
- cands_from_trigger (list): List of dictionaries with candidate data.
11
-
12
- Returns:
13
- list: List of contact dictionaries.
14
- """
15
- con_list = []
 
16
 
17
- for candidate in cands_from_trigger:
18
- contact = {
19
- "FirstName": candidate.get("First_Name__c", ""),
20
- "LastName": candidate.get("Last_Name__c", ""),
21
- "Email": candidate.get("Email__c", "")
22
- }
23
- con_list.append(contact)
 
 
 
 
 
24
 
25
- return con_list
26
 
27
- def process_json_input(json_input):
28
- """
29
- Process JSON input from Gradio text area and return contact records.
30
-
31
- Args:
32
- json_input (str): JSON string containing candidate data.
33
-
34
- Returns:
35
- str: JSON string of contact records or error message.
36
- """
37
- try:
38
- # Parse JSON input (expecting a list of dictionaries)
39
- candidates = json.loads(json_input)
40
- if not isinstance(candidates, list):
41
- return "Error: Input must be a JSON list of candidate objects."
42
-
43
- # Process candidates
44
- contacts = create_contact_from_can(candidates)
45
-
46
- # Return formatted JSON
47
- return json.dumps(contacts, indent=4)
48
- except json.JSONDecodeError:
49
- return "Error: Invalid JSON format. Please provide valid JSON, e.g., [{\"First_Name__c\": \"John\", \"Last_Name__c\": \"Doe\", \"Email__c\": \"john.doe@example.com\"}]"
50
- except Exception as e:
51
- return f"Error: {str(e)}"
52
 
53
- def process_form_input(first_name, last_name, email):
54
  """
55
- Process form input for a single candidate and return contact record.
56
 
57
  Args:
58
- first_name (str): Candidate's first name.
59
- last_name (str): Candidate's last name.
60
- email (str): Candidate's email.
61
 
62
  Returns:
63
- str: JSON string of the contact record.
64
  """
65
- candidate = {
66
- "First_Name__c": first_name,
67
- "Last_Name__c": last_name,
68
- "Email__c": email
69
- }
70
- contacts = create_contact_from_can([candidate])
71
- return json.dumps(contacts[0], indent=4)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
  # Define Gradio interface
74
- with gr.Blocks(title="Candidate to Contact Converter") as demo:
75
- gr.Markdown("# Candidate to Contact Converter")
76
- gr.Markdown("Convert candidate data to contact records. Use the JSON input for batch processing or the form for a single candidate.")
77
-
78
- # JSON Input Section
79
- gr.Markdown("## Batch Input (JSON)")
80
- gr.Markdown("Enter candidate data in JSON format (list of objects). Example:")
81
- gr.Markdown("""
82
- ```json
83
- [
84
- {"First_Name__c": "John", "Last_Name__c": "Doe", "Email__c": "john.doe@example.com"},
85
- {"First_Name__c": "Jane", "Last_Name__c": "Smith", "Email__c": "jane.smith@example.com"}
86
- ]
87
- ```
88
- """)
89
- json_input = gr.Textbox(label="Candidate JSON", lines=10)
90
- json_output = gr.Textbox(label="Contact Output (JSON)", lines=10, interactive=False)
91
- json_button = gr.Button("Convert JSON")
92
- json_button.click(fn=process_json_input, inputs=json_input, outputs=json_output)
93
 
94
- # Form Input Section
95
- gr.Markdown("## Single Candidate Form")
96
- first_name = gr.Textbox(label="First Name")
97
- last_name = gr.Textbox(label="Last Name")
98
- email = gr.Textbox(label="Email")
99
- form_output = gr.Textbox(label="Contact Output (JSON)", lines=5, interactive=False)
100
- form_button = gr.Button("Convert Form")
101
- form_button.click(fn=process_form_input, inputs=[first_name, last_name, email], outputs=form_output)
102
-
103
- # Download Output
104
- gr.Markdown("## Download Results")
105
- download_button = gr.File(label="Download Contacts as JSON")
106
-
107
- def prepare_download(json_output):
108
- if json_output and json_output.startswith("["):
109
- with open("contacts.json", "w") as f:
110
- f.write(json_output)
111
- return "contacts.json"
112
- return None
113
-
114
- json_output.change(fn=prepare_download, inputs=json_output, outputs=download_button)
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
  # Launch the app
117
  demo.launch()
 
1
  import gradio as gr
 
2
  import pandas as pd
3
+ import matplotlib.pyplot as plt
4
+ from datetime import datetime, timedelta
5
+ import random
6
 
7
+ # Simulate sample data for lab devices (mimicking Salesforce custom objects)
8
+ def generate_sample_data():
9
+ labs = ["Lab_A", "Lab_B", "Lab_C"]
10
+ equipment_types = ["Microscope", "Centrifuge", "UV_Sterilizer"]
11
+ devices = []
12
+ logs = []
13
 
14
+ # Generate devices
15
+ for i in range(10):
16
+ devices.append({
17
+ "Device_ID": f"DEV_{i+1}",
18
+ "Lab": random.choice(labs),
19
+ "Equipment_Type": random.choice(equipment_types),
20
+ "Status": random.choice(["Operational", "Down", "Maintenance"])
21
+ })
22
 
23
+ # Generate logs (simulating SmartLog__c, Cell_Analysis__c, etc.)
24
+ start_date = datetime.now() - timedelta(days=30)
25
+ for device in devices:
26
+ for day in range(30):
27
+ log_date = start_date + timedelta(days=day)
28
+ logs.append({
29
+ "Device_ID": device["Device_ID"],
30
+ "Log_Timestamp": log_date.strftime("%Y-%m-%d %H:%M:%S"),
31
+ "Usage_Count": random.randint(0, 100),
32
+ "Status": random.choice(["Operational", "Down", "Maintenance"]),
33
+ "AMC_Expiry": (log_date + timedelta(days=random.randint(10, 365))).strftime("%Y-%m-%d")
34
+ })
35
 
36
+ return pd.DataFrame(devices), pd.DataFrame(logs)
37
 
38
+ # Initialize sample data
39
+ devices_df, logs_df = generate_sample_data()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
+ def process_dashboard_data(lab_filter, equipment_type_filter, date_range):
42
  """
43
+ Process device and log data based on filters and return dashboard components.
44
 
45
  Args:
46
+ lab_filter (str): Selected lab (e.g., Lab_A or All).
47
+ equipment_type_filter (str): Selected equipment type (e.g., Microscope or All).
48
+ date_range (tuple): Start and end dates for filtering logs.
49
 
50
  Returns:
51
+ tuple: Device cards text, daily trend plot, uptime plot, anomaly alerts, report text.
52
  """
53
+ # Apply filters
54
+ filtered_devices = devices_df.copy()
55
+ if lab_filter != "All":
56
+ filtered_devices = filtered_devices[filtered_devices["Lab"] == lab_filter]
57
+ if equipment_type_filter != "All":
58
+ filtered_devices = filtered_devices[filtered_devices["Equipment_Type"] == equipment_type_filter]
59
+
60
+ filtered_logs = logs_df[logs_df["Device_ID"].isin(filtered_devices["Device_ID"])]
61
+ if date_range:
62
+ start_date, end_date = date_range
63
+ filtered_logs = filtered_logs[
64
+ (filtered_logs["Log_Timestamp"] >= start_date.strftime("%Y-%m-%d %H:%M:%S")) &
65
+ (filtered_logs["Log_Timestamp"] <= end_date.strftime("%Y-%m-%d %H:%M:%S"))
66
+ ]
67
+
68
+ # Device Cards
69
+ device_cards = "Device Cards:\n"
70
+ for _, device in filtered_devices.iterrows():
71
+ device_logs = filtered_logs[filtered_logs["Device_ID"] == device["Device_ID"]]
72
+ usage_count = device_logs["Usage_Count"].sum() if not device_logs.empty else 0
73
+ last_log = device_logs["Log_Timestamp"].max() if not device_logs.empty else "No logs"
74
+ device_cards += (
75
+ f"Device: {device['Device_ID']}, Lab: {device['Lab']}, Type: {device['Equipment_Type']}, "
76
+ f"Status: {device['Status']}, Usage Count: {usage_count}, Last Log: {last_log}\n"
77
+ )
78
+
79
+ # Daily Log Trends (Matplotlib Plot)
80
+ if not filtered_logs.empty:
81
+ filtered_logs["Date"] = pd.to_datetime(filtered_logs["Log_Timestamp"]).dt.date
82
+ daily_trends = filtered_logs.groupby("Date")["Usage_Count"].sum().reset_index()
83
+ plt.figure(figsize=(8, 4))
84
+ plt.plot(daily_trends["Date"], daily_trends["Usage_Count"], marker="o")
85
+ plt.title("Daily Log Trends")
86
+ plt.xlabel("Date")
87
+ plt.ylabel("Total Usage Count")
88
+ plt.xticks(rotation=45)
89
+ plt.tight_layout()
90
+ daily_trend_plot = plt.gcf()
91
+ else:
92
+ daily_trend_plot = None
93
+
94
+ # Weekly Uptime % (Matplotlib Plot)
95
+ if not filtered_logs.empty:
96
+ filtered_logs["Week"] = pd.to_datetime(filtered_logs["Log_Timestamp"]).dt.isocalendar().week
97
+ uptime_data = filtered_logs.groupby("Week")["Status"].value_counts().unstack(fill_value=0)
98
+ uptime_data["Uptime_%"] = uptime_data.get("Operational", 0) / (
99
+ uptime_data.get("Operational", 0) + uptime_data.get("Down", 0) + uptime_data.get("Maintenance", 0)
100
+ ) * 100
101
+ plt.figure(figsize=(8, 4))
102
+ plt.bar(uptime_data.index, uptime_data["Uptime_%"])
103
+ plt.title("Weekly Uptime %")
104
+ plt.xlabel("Week")
105
+ plt.ylabel("Uptime %")
106
+ plt.tight_layout()
107
+ uptime_plot = plt.gcf()
108
+ else:
109
+ uptime_plot = None
110
+
111
+ # Anomaly Alerts (Usage spikes: >2x average usage)
112
+ anomaly_alerts = "Anomaly Alerts:\n"
113
+ if not filtered_logs.empty:
114
+ avg_usage = filtered_logs["Usage_Count"].mean()
115
+ anomalies = filtered_logs[filtered_logs["Usage_Count"] > 2 * avg_usage]
116
+ for _, log in anomalies.iterrows():
117
+ anomaly_alerts += (
118
+ f"Device: {log['Device_ID']}, Timestamp: {log['Log_Timestamp']}, "
119
+ f"Usage Spike: {log['Usage_Count']} (Avg: {avg_usage:.2f})\n"
120
+ )
121
+
122
+ # AMC Reminders (simulated)
123
+ report = "LabOps Dashboard Report:\n"
124
+ report += f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
125
+ report += device_cards + "\n"
126
+ report += anomaly_alerts + "\n"
127
+ report += "AMC Reminders:\n"
128
+ if not filtered_logs.empty:
129
+ amc_expiring = filtered_logs[pd.to_datetime(filtered_logs["AMC_Expiry"]) <= (datetime.now() + timedelta(days=14))]
130
+ for _, log in amc_expiring.iterrows():
131
+ report += (
132
+ f"Device: {log['Device_ID']}, AMC Expiry: {log['AMC_Expiry']}\n"
133
+ )
134
+
135
+ return device_cards, daily_trend_plot, uptime_plot, anomaly_alerts, report
136
 
137
  # Define Gradio interface
138
+ with gr.Blocks(title="LabOps Dashboard") as demo:
139
+ gr.Markdown("# LabOps Dashboard")
140
+ gr.Markdown("Monitor smart lab devices, view usage trends, uptime, anomalies, and export reports.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
+ # Filters
143
+ gr.Markdown("## Filters")
144
+ lab_filter = gr.Dropdown(choices=["All"] + list(devices_df["Lab"].unique()), label="Lab Site")
145
+ equipment_type_filter = gr.Dropdown(choices=["All"] + list(devices_df["Equipment_Type"].unique()), label="Equipment Type")
146
+ date_range = gr.DateRange(label="Date Range")
147
+
148
+ # Dashboard Components
149
+ gr.Markdown("## Device Cards")
150
+ device_cards_output = gr.Textbox(label="Device Status", lines=10, interactive=False)
151
+ gr.Markdown("## Daily Log Trends")
152
+ daily_trend_plot = gr.Plot(label="Daily Usage Trends")
153
+ gr.Markdown("## Weekly Uptime %")
154
+ uptime_plot = gr.Plot(label="Weekly Uptime")
155
+ gr.Markdown("## Anomaly Alerts")
156
+ anomaly_alerts_output = gr.Textbox(label="Anomaly Alerts", lines=5, interactive=False)
157
+
158
+ # Export Report
159
+ gr.Markdown("## Export Report")
160
+ report_output = gr.Textbox(label="Report Preview", lines=10, interactive=False)
161
+ download_button = gr.File(label="Download Report as Text")
162
+
163
+ # Update dashboard on filter change
164
+ def update_dashboard(lab, equipment, date_range):
165
+ device_cards, daily_trend, uptime, anomalies, report = process_dashboard_data(lab, equipment, date_range)
166
+ with open("labops_report.txt", "w") as f:
167
+ f.write(report)
168
+ return device_cards, daily_trend, uptime, anomalies, report, "labops_report.txt"
169
+
170
+ gr.Button("Update Dashboard").click(
171
+ fn=update_dashboard,
172
+ inputs=[lab_filter, equipment_type_filter, date_range],
173
+ outputs=[device_cards_output, daily_trend_plot, uptime_plot, anomaly_alerts_output, report_output, download_button]
174
+ )
175
 
176
  # Launch the app
177
  demo.launch()