CCockrum commited on
Commit
c2a9902
·
verified ·
1 Parent(s): aac8463

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +450 -0
app.py ADDED
@@ -0,0 +1,450 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import pandas as pd
4
+ import matplotlib.pyplot as plt
5
+ from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
6
+ from sklearn.preprocessing import StandardScaler
7
+ from sklearn.metrics import classification_report, accuracy_score, mean_squared_error
8
+ import warnings
9
+ warnings.filterwarnings('ignore')
10
+
11
+ class F1PredictiveMaintenance:
12
+ def __init__(self):
13
+ self.failure_classifier = RandomForestClassifier(n_estimators=100, random_state=42)
14
+ self.wear_predictor = RandomForestRegressor(n_estimators=100, random_state=42)
15
+ self.scaler = StandardScaler()
16
+ self.is_trained = False
17
+
18
+ # Component definitions
19
+ self.components = {
20
+ 'Engine': {'max_cycles': 7, 'critical_temp': 120, 'normal_temp': 95},
21
+ 'Gearbox': {'max_cycles': 6, 'critical_temp': 100, 'normal_temp': 80},
22
+ 'Turbocharger': {'max_cycles': 4, 'critical_temp': 140, 'normal_temp': 110},
23
+ 'MGU-K': {'max_cycles': 5, 'critical_temp': 90, 'normal_temp': 70},
24
+ 'MGU-H': {'max_cycles': 4, 'critical_temp': 130, 'normal_temp': 105},
25
+ 'Suspension': {'max_cycles': 8, 'critical_temp': 60, 'normal_temp': 45},
26
+ 'Brakes': {'max_cycles': 3, 'critical_temp': 200, 'normal_temp': 150},
27
+ 'Tires': {'max_cycles': 1, 'critical_temp': 120, 'normal_temp': 80}
28
+ }
29
+
30
+ def generate_maintenance_data(self, num_samples=3000):
31
+ """Generate realistic F1 component maintenance data"""
32
+ np.random.seed(42)
33
+
34
+ data = []
35
+
36
+ for _ in range(num_samples):
37
+ # Select random component
38
+ component = np.random.choice(list(self.components.keys()))
39
+ comp_info = self.components[component]
40
+
41
+ # Usage parameters
42
+ race_weekend = np.random.randint(1, 25) # Race weekend number
43
+ session_type = np.random.choice(['Practice', 'Qualifying', 'Race'])
44
+ laps_completed = np.random.randint(10, 70)
45
+
46
+ # Session intensity (Race > Qualifying > Practice)
47
+ intensity_multiplier = {'Practice': 0.7, 'Qualifying': 1.0, 'Race': 1.2}[session_type]
48
+
49
+ # Environmental conditions
50
+ ambient_temp = np.random.uniform(15, 35) # °C
51
+ humidity = np.random.uniform(40, 90) # %
52
+ track_temp = ambient_temp + np.random.uniform(5, 25)
53
+
54
+ # Operating conditions
55
+ max_temp = comp_info['normal_temp'] + np.random.normal(0, 10) * intensity_multiplier
56
+ max_temp = np.clip(max_temp, comp_info['normal_temp'] * 0.8, comp_info['critical_temp'] * 1.2)
57
+
58
+ avg_temp = max_temp * 0.8 + np.random.normal(0, 5)
59
+ vibration = np.random.exponential(2) * intensity_multiplier
60
+ load_factor = np.random.uniform(0.6, 1.2) * intensity_multiplier
61
+
62
+ # Component age and usage
63
+ cycles_used = np.random.uniform(0, comp_info['max_cycles'] * 1.5)
64
+ total_laps = cycles_used * np.random.uniform(300, 800) # Laps per cycle
65
+
66
+ # Wear calculation
67
+ temp_stress = max(0, (max_temp - comp_info['normal_temp']) / comp_info['normal_temp'])
68
+ usage_stress = cycles_used / comp_info['max_cycles']
69
+ environmental_stress = (track_temp - 30) / 50 + humidity / 200
70
+
71
+ wear_level = (usage_stress * 0.4 + temp_stress * 0.3 +
72
+ vibration * 0.1 + load_factor * 0.1 + environmental_stress * 0.1)
73
+ wear_level = np.clip(wear_level, 0, 1)
74
+
75
+ # Failure prediction
76
+ failure_probability = wear_level ** 2
77
+ if component in ['Engine', 'Gearbox']:
78
+ failure_probability *= 0.8 # More reliable components
79
+ elif component in ['Turbocharger', 'MGU-H']:
80
+ failure_probability *= 1.3 # Less reliable components
81
+
82
+ # Add random failures
83
+ failure_risk = failure_probability > 0.7 or np.random.random() < 0.05
84
+
85
+ # Maintenance recommendations
86
+ if wear_level > 0.8:
87
+ maintenance_action = 'Replace'
88
+ elif wear_level > 0.6:
89
+ maintenance_action = 'Inspect'
90
+ elif wear_level > 0.4:
91
+ maintenance_action = 'Monitor'
92
+ else:
93
+ maintenance_action = 'Normal'
94
+
95
+ data.append({
96
+ 'component': component,
97
+ 'race_weekend': race_weekend,
98
+ 'session_type': session_type,
99
+ 'laps_completed': laps_completed,
100
+ 'ambient_temp': ambient_temp,
101
+ 'track_temp': track_temp,
102
+ 'humidity': humidity,
103
+ 'max_temp': max_temp,
104
+ 'avg_temp': avg_temp,
105
+ 'vibration': vibration,
106
+ 'load_factor': load_factor,
107
+ 'cycles_used': cycles_used,
108
+ 'total_laps': total_laps,
109
+ 'wear_level': wear_level,
110
+ 'failure_risk': failure_risk,
111
+ 'maintenance_action': maintenance_action
112
+ })
113
+
114
+ return pd.DataFrame(data)
115
+
116
+ def train_models(self, data):
117
+ """Train predictive maintenance models"""
118
+ # Prepare features
119
+ feature_columns = ['race_weekend', 'laps_completed', 'ambient_temp', 'track_temp',
120
+ 'humidity', 'max_temp', 'avg_temp', 'vibration', 'load_factor',
121
+ 'cycles_used', 'total_laps']
122
+
123
+ # Encode categorical variables
124
+ data_encoded = data.copy()
125
+ data_encoded['component_encoded'] = pd.Categorical(data['component']).codes
126
+ data_encoded['session_encoded'] = pd.Categorical(data['session_type']).codes
127
+
128
+ feature_columns.extend(['component_encoded', 'session_encoded'])
129
+
130
+ X = data_encoded[feature_columns]
131
+ X_scaled = self.scaler.fit_transform(X)
132
+
133
+ # Train failure classifier
134
+ y_failure = data['failure_risk']
135
+ self.failure_classifier.fit(X_scaled, y_failure)
136
+
137
+ # Train wear predictor
138
+ y_wear = data['wear_level']
139
+ self.wear_predictor.fit(X_scaled, y_wear)
140
+
141
+ self.is_trained = True
142
+
143
+ # Calculate performance metrics
144
+ failure_pred = self.failure_classifier.predict(X_scaled)
145
+ wear_pred = self.wear_predictor.predict(X_scaled)
146
+
147
+ failure_accuracy = accuracy_score(y_failure, failure_pred)
148
+ wear_rmse = np.sqrt(mean_squared_error(y_wear, wear_pred))
149
+
150
+ return failure_accuracy, wear_rmse, data_encoded
151
+
152
+ def predict_maintenance(self, component, race_weekend, session_type, laps_completed,
153
+ ambient_temp, track_temp, humidity, max_temp, avg_temp,
154
+ vibration, load_factor, cycles_used, total_laps):
155
+ """Predict maintenance requirements for a component"""
156
+ if not self.is_trained:
157
+ return "Model not trained", "Model not trained", "Model not trained"
158
+
159
+ # Encode inputs
160
+ component_encoded = list(self.components.keys()).index(component)
161
+ session_encoded = ['Practice', 'Qualifying', 'Race'].index(session_type)
162
+
163
+ # Prepare feature vector
164
+ features = np.array([[race_weekend, laps_completed, ambient_temp, track_temp,
165
+ humidity, max_temp, avg_temp, vibration, load_factor,
166
+ cycles_used, total_laps, component_encoded, session_encoded]])
167
+
168
+ features_scaled = self.scaler.transform(features)
169
+
170
+ # Make predictions
171
+ failure_prob = self.failure_classifier.predict_proba(features_scaled)[0][1]
172
+ wear_level = self.wear_predictor.predict(features_scaled)[0]
173
+
174
+ # Determine maintenance action
175
+ if wear_level > 0.8 or failure_prob > 0.7:
176
+ maintenance_action = "REPLACE - Critical wear detected"
177
+ elif wear_level > 0.6 or failure_prob > 0.5:
178
+ maintenance_action = "INSPECT - High wear detected"
179
+ elif wear_level > 0.4 or failure_prob > 0.3:
180
+ maintenance_action = "MONITOR - Moderate wear"
181
+ else:
182
+ maintenance_action = "NORMAL - Good condition"
183
+
184
+ return f"Failure Risk: {failure_prob:.1%}", f"Wear Level: {wear_level:.1%}", maintenance_action
185
+
186
+ def create_maintenance_dashboard(self, data):
187
+ """Create comprehensive maintenance visualization"""
188
+ fig, axes = plt.subplots(2, 2, figsize=(15, 12))
189
+
190
+ # Component reliability analysis
191
+ component_failure_rate = data.groupby('component')['failure_risk'].mean().sort_values(ascending=False)
192
+ bars = axes[0, 0].bar(component_failure_rate.index, component_failure_rate.values,
193
+ color='lightcoral', alpha=0.7)
194
+ axes[0, 0].set_title('Component Failure Risk Analysis')
195
+ axes[0, 0].set_ylabel('Failure Risk')
196
+ axes[0, 0].tick_params(axis='x', rotation=45)
197
+ axes[0, 0].grid(True, alpha=0.3)
198
+
199
+ # Add value labels on bars
200
+ for bar in bars:
201
+ height = bar.get_height()
202
+ axes[0, 0].text(bar.get_x() + bar.get_width()/2., height,
203
+ f'{height:.1%}', ha='center', va='bottom')
204
+
205
+ # Wear level distribution
206
+ axes[0, 1].hist(data['wear_level'], bins=20, alpha=0.7, color='skyblue', edgecolor='black')
207
+ axes[0, 1].axvline(data['wear_level'].mean(), color='red', linestyle='--',
208
+ label=f'Mean: {data["wear_level"].mean():.2f}')
209
+ axes[0, 1].set_title('Component Wear Distribution')
210
+ axes[0, 1].set_xlabel('Wear Level')
211
+ axes[0, 1].set_ylabel('Frequency')
212
+ axes[0, 1].legend()
213
+ axes[0, 1].grid(True, alpha=0.3)
214
+
215
+ # Temperature vs Wear correlation
216
+ scatter = axes[1, 0].scatter(data['max_temp'], data['wear_level'],
217
+ c=data['failure_risk'], cmap='RdYlBu_r', alpha=0.6)
218
+ axes[1, 0].set_xlabel('Maximum Temperature (°C)')
219
+ axes[1, 0].set_ylabel('Wear Level')
220
+ axes[1, 0].set_title('Temperature Impact on Component Wear')
221
+ plt.colorbar(scatter, ax=axes[1, 0], label='Failure Risk')
222
+ axes[1, 0].grid(True, alpha=0.3)
223
+
224
+ # Maintenance action recommendations
225
+ maintenance_counts = data['maintenance_action'].value_counts()
226
+ wedges, texts, autotexts = axes[1, 1].pie(maintenance_counts.values,
227
+ labels=maintenance_counts.index,
228
+ autopct='%1.1f%%', startangle=90)
229
+ axes[1, 1].set_title('Maintenance Action Distribution')
230
+
231
+ plt.tight_layout()
232
+ return fig
233
+
234
+ def generate_maintenance_schedule(self, data):
235
+ """Generate maintenance schedule recommendations"""
236
+ schedule = []
237
+
238
+ for component in self.components.keys():
239
+ comp_data = data[data['component'] == component]
240
+
241
+ if len(comp_data) == 0:
242
+ continue
243
+
244
+ avg_wear = comp_data['wear_level'].mean()
245
+ failure_rate = comp_data['failure_risk'].mean()
246
+
247
+ # Calculate recommended maintenance interval
248
+ if failure_rate > 0.3:
249
+ interval = "Every race weekend"
250
+ elif failure_rate > 0.15:
251
+ interval = "Every 2 race weekends"
252
+ elif failure_rate > 0.05:
253
+ interval = "Every 3 race weekends"
254
+ else:
255
+ interval = "Every 4 race weekends"
256
+
257
+ # Priority based on criticality
258
+ if component in ['Engine', 'Gearbox']:
259
+ priority = "High"
260
+ elif component in ['Turbocharger', 'MGU-K', 'MGU-H']:
261
+ priority = "Critical"
262
+ else:
263
+ priority = "Medium"
264
+
265
+ schedule.append({
266
+ 'Component': component,
267
+ 'Average Wear': f"{avg_wear:.1%}",
268
+ 'Failure Rate': f"{failure_rate:.1%}",
269
+ 'Recommended Interval': interval,
270
+ 'Priority': priority
271
+ })
272
+
273
+ return pd.DataFrame(schedule)
274
+
275
+ # Initialize the maintenance system
276
+ maintenance_system = F1PredictiveMaintenance()
277
+
278
+ def analyze_maintenance_data():
279
+ """Analyze maintenance data and train models"""
280
+ # Generate data
281
+ data = maintenance_system.generate_maintenance_data(3000)
282
+
283
+ # Train models
284
+ failure_acc, wear_rmse, data_encoded = maintenance_system.train_models(data)
285
+
286
+ # Create visualizations
287
+ fig = maintenance_system.create_maintenance_dashboard(data)
288
+
289
+ # Generate maintenance schedule
290
+ schedule = maintenance_system.generate_maintenance_schedule(data)
291
+
292
+ # Create summary report
293
+ report = f"""
294
+ ## F1 Predictive Maintenance Analysis
295
+
296
+ **Model Performance:**
297
+ - Failure Prediction Accuracy: {failure_acc:.1%}
298
+ - Wear Level RMSE: {wear_rmse:.3f}
299
+
300
+ **Fleet Analysis:**
301
+ - Total components analyzed: {len(data)}
302
+ - Average wear level: {data['wear_level'].mean():.1%}
303
+ - Components at risk: {(data['wear_level'] > 0.6).sum()}
304
+ - High-priority maintenance: {(data['maintenance_action'] == 'Replace').sum()}
305
+
306
+ **Risk Assessment:**
307
+ - Highest risk component: {data.groupby('component')['failure_risk'].mean().idxmax()}
308
+ - Most reliable component: {data.groupby('component')['failure_risk'].mean().idxmin()}
309
+ - Critical temperature events: {(data['max_temp'] > 120).sum()}
310
+
311
+ **Maintenance Recommendations:**
312
+ - Immediate attention needed: {(data['wear_level'] > 0.8).sum()} components
313
+ - Scheduled inspection: {(data['wear_level'] > 0.6).sum()} components
314
+ - Monitoring required: {(data['wear_level'] > 0.4).sum()} components
315
+ """
316
+
317
+ return fig, report, schedule
318
+
319
+ def predict_component_maintenance(component, race_weekend, session_type, laps_completed,
320
+ ambient_temp, track_temp, humidity, max_temp, avg_temp,
321
+ vibration, load_factor, cycles_used, total_laps):
322
+ """Predict maintenance for specific component"""
323
+ if not maintenance_system.is_trained:
324
+ return "Please run the analysis first!", "", ""
325
+
326
+ failure_risk, wear_level, maintenance_action = maintenance_system.predict_maintenance(
327
+ component, race_weekend, session_type, laps_completed,
328
+ ambient_temp, track_temp, humidity, max_temp, avg_temp,
329
+ vibration, load_factor, cycles_used, total_laps
330
+ )
331
+
332
+ return failure_risk, wear_level, maintenance_action
333
+
334
+ # Create Gradio interface
335
+ with gr.Blocks(title="F1 Predictive Maintenance System", theme=gr.themes.Soft()) as demo:
336
+ gr.Markdown("# F1 Predictive Maintenance System")
337
+ gr.Markdown("AI-powered predictive maintenance for Formula 1 components with failure prediction and wear analysis.")
338
+
339
+ with gr.Tab("Maintenance Analysis"):
340
+ gr.Markdown("### Analyze component reliability and maintenance requirements")
341
+ analyze_btn = gr.Button("Analyze Fleet Data", variant="primary")
342
+
343
+ with gr.Row():
344
+ with gr.Column(scale=2):
345
+ maintenance_plot = gr.Plot(label="Maintenance Dashboard")
346
+ with gr.Column(scale=1):
347
+ maintenance_report = gr.Markdown(label="Analysis Report")
348
+
349
+ with gr.Row():
350
+ maintenance_schedule = gr.DataFrame(label="Maintenance Schedule", interactive=False)
351
+
352
+ analyze_btn.click(
353
+ analyze_maintenance_data,
354
+ outputs=[maintenance_plot, maintenance_report, maintenance_schedule]
355
+ )
356
+
357
+ with gr.Tab("Component Prediction"):
358
+ gr.Markdown("### Predict maintenance requirements for specific components")
359
+ gr.Markdown("*Note: Run the analysis first to train the models*")
360
+
361
+ with gr.Row():
362
+ with gr.Column():
363
+ gr.Markdown("**Component Information:**")
364
+ component_select = gr.Dropdown(
365
+ choices=list(maintenance_system.components.keys()),
366
+ value="Engine",
367
+ label="Component"
368
+ )
369
+ race_weekend_input = gr.Slider(1, 25, value=10, label="Race Weekend")
370
+ session_type_select = gr.Dropdown(
371
+ choices=["Practice", "Qualifying", "Race"],
372
+ value="Race",
373
+ label="Session Type"
374
+ )
375
+ laps_input = gr.Slider(10, 70, value=50, label="Laps Completed")
376
+
377
+ gr.Markdown("**Operating Conditions:**")
378
+ ambient_temp_input = gr.Slider(15, 35, value=25, label="Ambient Temperature (°C)")
379
+ track_temp_input = gr.Slider(20, 60, value=40, label="Track Temperature (°C)")
380
+ humidity_input = gr.Slider(40, 90, value=65, label="Humidity (%)")
381
+ max_temp_input = gr.Slider(60, 200, value=100, label="Max Component Temperature (°C)")
382
+ avg_temp_input = gr.Slider(50, 150, value=85, label="Average Temperature (°C)")
383
+
384
+ with gr.Column():
385
+ gr.Markdown("**Component Usage:**")
386
+ vibration_input = gr.Slider(0, 10, value=2, label="Vibration Level")
387
+ load_factor_input = gr.Slider(0.5, 1.5, value=1.0, label="Load Factor")
388
+ cycles_input = gr.Slider(0, 10, value=3, label="Cycles Used")
389
+ total_laps_input = gr.Slider(0, 5000, value=1500, label="Total Laps")
390
+
391
+ predict_btn = gr.Button("Predict Maintenance", variant="secondary")
392
+
393
+ gr.Markdown("**Predictions:**")
394
+ failure_risk_output = gr.Textbox(label="Failure Risk", interactive=False)
395
+ wear_level_output = gr.Textbox(label="Wear Level", interactive=False)
396
+ maintenance_action_output = gr.Textbox(label="Maintenance Action", interactive=False)
397
+
398
+ predict_btn.click(
399
+ predict_component_maintenance,
400
+ inputs=[component_select, race_weekend_input, session_type_select, laps_input,
401
+ ambient_temp_input, track_temp_input, humidity_input, max_temp_input,
402
+ avg_temp_input, vibration_input, load_factor_input, cycles_input, total_laps_input],
403
+ outputs=[failure_risk_output, wear_level_output, maintenance_action_output]
404
+ )
405
+
406
+ with gr.Tab("About"):
407
+ gr.Markdown("""
408
+ ## About This System
409
+
410
+ This F1 Predictive Maintenance System uses advanced AI to predict component failures and optimize maintenance schedules:
411
+
412
+ **Failure Prediction:**
413
+ - Random Forest Classifier predicts component failure risk
414
+ - Considers operating conditions, usage patterns, and environmental factors
415
+ - Provides early warning for potential failures
416
+
417
+ **Wear Analysis:**
418
+ - Machine learning model predicts component wear levels
419
+ - Accounts for temperature stress, vibration, and load factors
420
+ - Enables proactive maintenance scheduling
421
+
422
+ **Key Features:**
423
+ - Real-time component health monitoring
424
+ - Predictive maintenance recommendations
425
+ - Temperature and environmental impact analysis
426
+ - Maintenance schedule optimization
427
+ - Component reliability assessment
428
+
429
+ **Component Coverage:**
430
+ - Engine and power unit components
431
+ - Transmission and drivetrain
432
+ - Hybrid energy systems (MGU-K, MGU-H)
433
+ - Suspension and braking systems
434
+ - Tires and consumables
435
+
436
+ **Technical Implementation:**
437
+ - Random Forest algorithms for robust predictions
438
+ - Feature engineering for component-specific factors
439
+ - Time-series analysis for wear progression
440
+ - Risk assessment and priority classification
441
+
442
+ **Racing Applications:**
443
+ - Prevent costly race retirements
444
+ - Optimize component allocation across seasons
445
+ - Reduce unexpected failures during critical sessions
446
+ - Enhance reliability through data-driven maintenance
447
+ """)
448
+
449
+ if __name__ == "__main__":
450
+ demo.launch()