VaneshDev commited on
Commit
7c8bda5
·
verified ·
1 Parent(s): 0cc0db9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -87
app.py CHANGED
@@ -1,105 +1,191 @@
1
- import gradio as gr
2
  import pandas as pd
3
- import numpy as np
4
- import matplotlib.pyplot as plt
5
- import seaborn as sns
6
- from sklearn.linear_model import LogisticRegression
7
- from sklearn.preprocessing import StandardScaler
8
- import io
9
- import base64
10
 
11
- # Load equipment data
12
- def load_data():
13
- df = pd.read_csv("equipment_data.csv")
14
- return df
15
 
16
- # Mock AI model for suggestions
17
- def predict_suggestions(df):
18
- X = df[["Usage_Hours__c", "Idle_Hours__c", "Utilization_Score__c"]].fillna(0)
19
- scaler = StandardScaler()
20
- X_scaled = scaler.fit_transform(X)
21
-
22
- suggestions = ["Move", "Pause Rent", "Repair", "Replace"]
23
- y = np.random.choice(suggestions, size=len(df)) # Mock model
24
-
25
- model = LogisticRegression()
26
- model.fit(X_scaled, y)
27
-
28
- probs = model.predict_proba(X_scaled)
29
- df["AI_Suggestion__c"] = model.predict(X_scaled)
30
- df["Suggestion_Confidence__c"] = probs.max(axis=1) * 100
31
- return df
32
 
33
- # Generate equipment cards
34
- def generate_cards(df, project_filter, suggestion_filter):
35
- filtered_df = df
36
- if project_filter and project_filter != "All":
37
- filtered_df = filtered_df[filtered_df["Project_ID__c"] == project_filter]
38
- if suggestion_filter and suggestion_filter != "All":
39
- filtered_df = filtered_df[filtered_df["AI_Suggestion__c"] == suggestion_filter]
40
-
41
- cards = ""
42
- for _, row in filtered_df.iterrows():
43
- card = f"""
44
- **Equipment ID**: {row['Equipment_ID__c']}
45
- **Project**: {row['Project_ID__c']}
46
- **Usage Hours**: {row['Usage_Hours__c']}
47
- **Idle Hours**: {row['Idle_Hours__c']}
48
- **Utilization Score**: {row['Utilization_Score__c']}%
49
- **AI Suggestion**: {row['AI_Suggestion__c']} (Confidence: {row['Suggestion_Confidence__c']:.2f}%)
50
- **Last Maintenance**: {row['Last_Maintenance__c']}
51
- """
52
- cards += card + "\n---\n"
53
- return cards if cards else "No equipment matches the filters."
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
- # Generate heatmap
56
- def generate_heatmap(df):
57
- dates = pd.date_range(start="2025-05-01", end="2025-05-07", freq="D")
58
- equipment = df["Equipment_ID__c"].unique()
59
- heatmap_data = np.random.rand(len(equipment), len(dates)) * 100 # Mock data
60
- plt.figure(figsize=(10, 6))
61
- sns.heatmap(heatmap_data, xticklabels=dates.strftime("%Y-%m-%d"), yticklabels=equipment, cmap="YlGnBu")
62
- plt.title("Weekly Utilization Heatmap")
63
-
64
- buffer = io.BytesIO()
65
- plt.savefig(buffer, format="png")
66
- buffer.seek(0)
67
- img_str = base64.b64encode(buffer.getvalue()).decode()
68
- plt.close()
69
- return f"![Heatmap](data:image/png;base64,{img_str})"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
- # Export data as CSV
72
- def export_csv(df):
73
- return df.to_csv(index=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
- # Main Gradio interface
76
- def main(project_filter="All", suggestion_filter="All"):
77
- df = load_data()
78
- df = predict_suggestions(df)
79
- cards = generate_cards(df, project_filter, suggestion_filter)
80
- heatmap = generate_heatmap(df)
81
- csv_data = export_csv(df)
82
- return cards, heatmap, csv_data
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
- # Gradio interface
85
- with gr.Blocks() as demo:
86
  gr.Markdown("# Equipment Utilization Dashboard")
 
87
 
88
  with gr.Row():
89
- project_filter = gr.Dropdown(choices=["All", "PRJ001", "PRJ002"], label="Filter by Project")
90
- suggestion_filter = gr.Dropdown(choices=["All", "Move", "Pause Rent", "Repair", "Replace"], label="Filter by Suggestion")
 
91
 
92
- with gr.Row():
93
- cards_output = gr.Markdown(label="Equipment Cards")
94
 
95
  with gr.Row():
96
- heatmap_output = gr.Markdown(label="Utilization Heatmap")
97
 
98
- with gr.Row():
99
- export_button = gr.File(label="Download CSV", value=lambda: export_csv(load_data()))
100
 
101
- project_filter.change(main, inputs=[project_filter, suggestion_filter], outputs=[cards_output, heatmap_output, export_button])
102
- suggestion_filter.change(main, inputs=[project_filter, suggestion_filter], outputs=[cards_output, heatmap_output, export_button])
 
 
 
 
 
 
103
 
 
104
  if __name__ == "__main__":
105
- demo.launch()
 
 
 
 
 
1
  import pandas as pd
2
+ import requests
3
+ import gradio as gr
4
+ import logging
5
+ from uuid import uuid4
 
 
 
6
 
7
+ # Configure logging
8
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
9
+ logger = logging.getLogger(__name__)
 
10
 
11
+ # FastAPI endpoint
12
+ FASTAPI_ENDPOINT = "http://localhost:8000/predict"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
+ # Load and validate dataset
15
+ def load_dataset(file_path="equipment_data.csv"):
16
+ try:
17
+ df = pd.read_csv(file_path)
18
+ required_columns = ["Equipment_ID__c", "Equipment_Type__c", "Usage_Hours__c", "Idle_Hours__c"]
19
+ optional_columns = ["Movement_Frequency__c", "Cost_Per_Hour__c"]
20
+ missing_required = [col for col in required_columns if col not in df.columns]
21
+ if missing_required:
22
+ logger.error(f"Missing required columns: {missing_required}")
23
+ return None
24
+
25
+ # Ensure numeric columns are properly typed
26
+ numeric_cols = [col for col in required_columns + optional_columns if col in df.columns and col != "Equipment_ID__c" and col != "Equipment_Type__c"]
27
+ for col in numeric_cols:
28
+ df[col] = pd.to_numeric(df[col], errors='coerce')
29
+
30
+ # Fill NaN values in numeric columns with 0
31
+ if df[numeric_cols].isnull().any().any():
32
+ logger.warning("NaN values detected in numeric columns, filling with 0")
33
+ df[numeric_cols] = df[numeric_cols].fillna(0)
34
+
35
+ # Add missing optional columns with default value 0
36
+ for col in optional_columns:
37
+ if col not in df.columns:
38
+ logger.warning(f"Optional column {col} missing, adding with default value 0")
39
+ df[col] = 0.0
40
+
41
+ return df
42
+ except FileNotFoundError:
43
+ logger.error(f"Dataset file {file_path} not found")
44
+ return None
45
+ except Exception as e:
46
+ logger.error(f"Failed to load dataset: {e}")
47
+ return None
48
 
49
+ # Load dataset
50
+ df = load_dataset()
51
+ equipment_types = sorted(df["Equipment_Type__c"].dropna().unique().tolist()) if df is not None and not df.empty else ["No Equipment Types"]
52
+ suggestion_types = ["Move", "Pause Rent", "Repair", "Replace"]
53
+
54
+ # Call FastAPI endpoint
55
+ def call_model(row):
56
+ try:
57
+ # Prepare inputs
58
+ inputs = {
59
+ "usage_hours": float(row["Usage_Hours__c"]),
60
+ "idle_hours": float(row["Idle_Hours__c"]),
61
+ "movement_frequency": float(row.get("Movement_Frequency__c", 0.0)),
62
+ "cost_per_hour": float(row.get("Cost_Per_Hour__c", 0.0))
63
+ }
64
+
65
+ logger.info(f"Sending request with inputs: {inputs}") # Log inputs
66
+
67
+ response = requests.post(FASTAPI_ENDPOINT, json=inputs, timeout=10)
68
+ response.raise_for_status()
69
+ result = response.json()
70
+
71
+ # Log the API response
72
+ logger.info(f"Received response: {result}")
73
+
74
+ suggestion = result.get("suggestion", "Replace")
75
+ confidence = float(result.get("confidence", 0.5))
76
+
77
+ if suggestion not in suggestion_types:
78
+ logger.warning(f"Invalid suggestion: {suggestion}, defaulting to Replace")
79
+ suggestion = "Replace"
80
+
81
+ if not (0 <= confidence <= 1):
82
+ logger.warning(f"Invalid confidence: {confidence}, defaulting to 0.5")
83
+ confidence = 0.5
84
+
85
+ return suggestion, confidence
86
+ except (requests.RequestException, ValueError, KeyError) as e:
87
+ logger.error(f"API call failed: {e}")
88
+ return "Replace", 0.5
89
 
90
+ # Filter equipment and generate display
91
+ def filter_equipment(equipment_type, suggestion):
92
+ if not equipment_type or not suggestion or df is None or df.empty:
93
+ return "No data available or invalid filters selected.", ""
94
+
95
+ try:
96
+ filtered = df[df["Equipment_Type__c"].str.lower() == equipment_type.lower()].copy()
97
+ if filtered.empty:
98
+ return f"No equipment found for type: {equipment_type}.", ""
99
+
100
+ # Apply model predictions
101
+ filtered["AI_Suggestion__c"] = None
102
+ filtered["Suggestion_Confidence__c"] = 0.0
103
+ for idx, row in filtered.iterrows():
104
+ s, conf = call_model(row)
105
+ filtered.at[idx, "AI_Suggestion__c"] = s
106
+ filtered.at[idx, "Suggestion_Confidence__c"] = conf
107
+
108
+ # Filter by suggestion
109
+ filtered = filtered[filtered["AI_Suggestion__c"].str.lower() == suggestion.lower()]
110
+ if filtered.empty:
111
+ return f"No equipment with suggestion '{suggestion}' for type '{equipment_type}'.", ""
112
+
113
+ # Generate display cards
114
+ cards = [
115
+ f"ID: {row['Equipment_ID__c']} | Usage: {row['Usage_Hours__c']:.2f} hrs | "
116
+ f"Idle: {row['Idle_Hours__c']:.2f} hrs | Move Freq: {row['Movement_Frequency__c']:.2f} | "
117
+ f"Cost/hr: ${row['Cost_Per_Hour__c']:.2f} | AI: {row['AI_Suggestion__c']} "
118
+ f"({row['Suggestion_Confidence__c']:.2%})"
119
+ for _, row in filtered.iterrows()
120
+ ]
121
+ confidences = [f"{row['Equipment_ID__c']}: {row['Suggestion_Confidence__c']:.2%}"
122
+ for _, row in filtered.iterrows()]
123
+ return "\n\n".join(cards), "\n".join(confidences)
124
+ except Exception as e:
125
+ logger.error(f"Error in filter_equipment: {e}")
126
+ return "An error occurred while filtering equipment.", ""
127
 
128
+ # Export filtered data to CSV
129
+ def export_csv(equipment_type, suggestion):
130
+ if not equipment_type or not suggestion or df is None or df.empty:
131
+ return None
132
+
133
+ try:
134
+ filtered = df[df["Equipment_Type__c"].str.lower() == equipment_type.lower()].copy()
135
+ if filtered.empty:
136
+ return None
137
+
138
+ # Apply model predictions
139
+ filtered["AI_Suggestion__c"] = None
140
+ filtered["Suggestion_Confidence__c"] = 0.0
141
+ for idx, row in filtered.iterrows():
142
+ s, conf = call_model(row)
143
+ filtered.at[idx, "AI_Suggestion__c"] = s
144
+ filtered.at[idx, "Suggestion_Confidence__c"] = conf
145
+
146
+ # Filter by suggestion
147
+ filtered = filtered[filtered["AI_Suggestion__c"].str.lower() == suggestion.lower()]
148
+ if filtered.empty:
149
+ return None
150
+
151
+ # Export to CSV
152
+ filename = f"filtered_equipment_{uuid4().hex[:8]}.csv"
153
+ filtered.to_csv(filename, index=False)
154
+ return filename
155
+ except Exception as e:
156
+ logger.error(f"Error in export_csv: {e}")
157
+ return None
158
 
159
+ # Build Gradio UI
160
+ with gr.Blocks(theme=gr.themes.Soft()) as app:
161
  gr.Markdown("# Equipment Utilization Dashboard")
162
+ gr.Markdown("Filter equipment by type and AI suggestion to optimize utilization.")
163
 
164
  with gr.Row():
165
+ etype = gr.Dropdown(choices=equipment_types, label="Equipment Type",
166
+ value=equipment_types[0] if equipment_types else None)
167
+ suggestion = gr.Dropdown(choices=suggestion_types, label="Suggestion Type", value=suggestion_types[0])
168
 
169
+ results = gr.Textbox(label="Equipment Details", lines=10, placeholder="Select equipment type and suggestion...")
170
+ confidences = gr.Textbox(label="Confidence Scores", lines=5, placeholder="Confidence scores will appear here...")
171
 
172
  with gr.Row():
173
+ export_button = gr.Button("Export to CSV", variant="primary")
174
 
175
+ file_output = gr.File(label="Download CSV")
 
176
 
177
+ # Define interactions
178
+ etype.change(fn=filter_equipment, inputs=[etype, suggestion], outputs=[results, confidences])
179
+ suggestion.change(fn=filter_equipment, inputs=[etype, suggestion], outputs=[results, confidences])
180
+ export_button.click(
181
+ fn=export_csv,
182
+ inputs=[etype, suggestion],
183
+ outputs=file_output
184
+ )
185
 
186
+ # Launch the app
187
  if __name__ == "__main__":
188
+ try:
189
+ app.launch(debug=False, share=False)
190
+ except Exception as e:
191
+ logger.error(f"Failed to launch Gradio app: {e}")