|
import gradio as gr |
|
import numpy as np |
|
import pandas as pd |
|
import matplotlib.pyplot as plt |
|
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor |
|
from sklearn.preprocessing import StandardScaler |
|
from sklearn.metrics import classification_report, accuracy_score, mean_squared_error |
|
import warnings |
|
warnings.filterwarnings('ignore') |
|
|
|
class F1PredictiveMaintenance: |
|
def __init__(self): |
|
self.failure_classifier = RandomForestClassifier(n_estimators=100, random_state=42) |
|
self.wear_predictor = RandomForestRegressor(n_estimators=100, random_state=42) |
|
self.scaler = StandardScaler() |
|
self.is_trained = False |
|
|
|
|
|
self.components = { |
|
'Engine': {'max_cycles': 7, 'critical_temp': 120, 'normal_temp': 95}, |
|
'Gearbox': {'max_cycles': 6, 'critical_temp': 100, 'normal_temp': 80}, |
|
'Turbocharger': {'max_cycles': 4, 'critical_temp': 140, 'normal_temp': 110}, |
|
'MGU-K': {'max_cycles': 5, 'critical_temp': 90, 'normal_temp': 70}, |
|
'MGU-H': {'max_cycles': 4, 'critical_temp': 130, 'normal_temp': 105}, |
|
'Suspension': {'max_cycles': 8, 'critical_temp': 60, 'normal_temp': 45}, |
|
'Brakes': {'max_cycles': 3, 'critical_temp': 200, 'normal_temp': 150}, |
|
'Tires': {'max_cycles': 1, 'critical_temp': 120, 'normal_temp': 80} |
|
} |
|
|
|
def generate_maintenance_data(self, num_samples=3000): |
|
"""Generate realistic F1 component maintenance data""" |
|
np.random.seed(42) |
|
|
|
data = [] |
|
|
|
for _ in range(num_samples): |
|
|
|
component = np.random.choice(list(self.components.keys())) |
|
comp_info = self.components[component] |
|
|
|
|
|
race_weekend = np.random.randint(1, 25) |
|
session_type = np.random.choice(['Practice', 'Qualifying', 'Race']) |
|
laps_completed = np.random.randint(10, 70) |
|
|
|
|
|
intensity_multiplier = {'Practice': 0.7, 'Qualifying': 1.0, 'Race': 1.2}[session_type] |
|
|
|
|
|
ambient_temp = np.random.uniform(15, 35) |
|
humidity = np.random.uniform(40, 90) |
|
track_temp = ambient_temp + np.random.uniform(5, 25) |
|
|
|
|
|
max_temp = comp_info['normal_temp'] + np.random.normal(0, 10) * intensity_multiplier |
|
max_temp = np.clip(max_temp, comp_info['normal_temp'] * 0.8, comp_info['critical_temp'] * 1.2) |
|
|
|
avg_temp = max_temp * 0.8 + np.random.normal(0, 5) |
|
vibration = np.random.exponential(2) * intensity_multiplier |
|
load_factor = np.random.uniform(0.6, 1.2) * intensity_multiplier |
|
|
|
|
|
cycles_used = np.random.uniform(0, comp_info['max_cycles'] * 1.5) |
|
total_laps = cycles_used * np.random.uniform(300, 800) |
|
|
|
|
|
temp_stress = max(0, (max_temp - comp_info['normal_temp']) / comp_info['normal_temp']) |
|
usage_stress = cycles_used / comp_info['max_cycles'] |
|
environmental_stress = (track_temp - 30) / 50 + humidity / 200 |
|
|
|
wear_level = (usage_stress * 0.4 + temp_stress * 0.3 + |
|
vibration * 0.1 + load_factor * 0.1 + environmental_stress * 0.1) |
|
wear_level = np.clip(wear_level, 0, 1) |
|
|
|
|
|
failure_probability = wear_level ** 2 |
|
if component in ['Engine', 'Gearbox']: |
|
failure_probability *= 0.8 |
|
elif component in ['Turbocharger', 'MGU-H']: |
|
failure_probability *= 1.3 |
|
|
|
|
|
failure_risk = failure_probability > 0.7 or np.random.random() < 0.05 |
|
|
|
|
|
if wear_level > 0.8: |
|
maintenance_action = 'Replace' |
|
elif wear_level > 0.6: |
|
maintenance_action = 'Inspect' |
|
elif wear_level > 0.4: |
|
maintenance_action = 'Monitor' |
|
else: |
|
maintenance_action = 'Normal' |
|
|
|
data.append({ |
|
'component': component, |
|
'race_weekend': race_weekend, |
|
'session_type': session_type, |
|
'laps_completed': laps_completed, |
|
'ambient_temp': ambient_temp, |
|
'track_temp': track_temp, |
|
'humidity': humidity, |
|
'max_temp': max_temp, |
|
'avg_temp': avg_temp, |
|
'vibration': vibration, |
|
'load_factor': load_factor, |
|
'cycles_used': cycles_used, |
|
'total_laps': total_laps, |
|
'wear_level': wear_level, |
|
'failure_risk': failure_risk, |
|
'maintenance_action': maintenance_action |
|
}) |
|
|
|
return pd.DataFrame(data) |
|
|
|
def train_models(self, data): |
|
"""Train predictive maintenance models""" |
|
|
|
feature_columns = ['race_weekend', 'laps_completed', 'ambient_temp', 'track_temp', |
|
'humidity', 'max_temp', 'avg_temp', 'vibration', 'load_factor', |
|
'cycles_used', 'total_laps'] |
|
|
|
|
|
data_encoded = data.copy() |
|
data_encoded['component_encoded'] = pd.Categorical(data['component']).codes |
|
data_encoded['session_encoded'] = pd.Categorical(data['session_type']).codes |
|
|
|
feature_columns.extend(['component_encoded', 'session_encoded']) |
|
|
|
X = data_encoded[feature_columns] |
|
X_scaled = self.scaler.fit_transform(X) |
|
|
|
|
|
y_failure = data['failure_risk'] |
|
self.failure_classifier.fit(X_scaled, y_failure) |
|
|
|
|
|
y_wear = data['wear_level'] |
|
self.wear_predictor.fit(X_scaled, y_wear) |
|
|
|
self.is_trained = True |
|
|
|
|
|
failure_pred = self.failure_classifier.predict(X_scaled) |
|
wear_pred = self.wear_predictor.predict(X_scaled) |
|
|
|
failure_accuracy = accuracy_score(y_failure, failure_pred) |
|
wear_rmse = np.sqrt(mean_squared_error(y_wear, wear_pred)) |
|
|
|
return failure_accuracy, wear_rmse, data_encoded |
|
|
|
def predict_maintenance(self, component, race_weekend, session_type, laps_completed, |
|
ambient_temp, track_temp, humidity, max_temp, avg_temp, |
|
vibration, load_factor, cycles_used, total_laps): |
|
"""Predict maintenance requirements for a component""" |
|
if not self.is_trained: |
|
return "Model not trained", "Model not trained", "Model not trained" |
|
|
|
|
|
component_encoded = list(self.components.keys()).index(component) |
|
session_encoded = ['Practice', 'Qualifying', 'Race'].index(session_type) |
|
|
|
|
|
features = np.array([[race_weekend, laps_completed, ambient_temp, track_temp, |
|
humidity, max_temp, avg_temp, vibration, load_factor, |
|
cycles_used, total_laps, component_encoded, session_encoded]]) |
|
|
|
features_scaled = self.scaler.transform(features) |
|
|
|
|
|
failure_prob = self.failure_classifier.predict_proba(features_scaled)[0][1] |
|
wear_level = self.wear_predictor.predict(features_scaled)[0] |
|
|
|
|
|
if wear_level > 0.8 or failure_prob > 0.7: |
|
maintenance_action = "REPLACE - Critical wear detected" |
|
elif wear_level > 0.6 or failure_prob > 0.5: |
|
maintenance_action = "INSPECT - High wear detected" |
|
elif wear_level > 0.4 or failure_prob > 0.3: |
|
maintenance_action = "MONITOR - Moderate wear" |
|
else: |
|
maintenance_action = "NORMAL - Good condition" |
|
|
|
return f"Failure Risk: {failure_prob:.1%}", f"Wear Level: {wear_level:.1%}", maintenance_action |
|
|
|
def create_maintenance_dashboard(self, data): |
|
"""Create comprehensive maintenance visualization""" |
|
fig, axes = plt.subplots(2, 2, figsize=(15, 12)) |
|
|
|
|
|
component_failure_rate = data.groupby('component')['failure_risk'].mean().sort_values(ascending=False) |
|
bars = axes[0, 0].bar(component_failure_rate.index, component_failure_rate.values, |
|
color='lightcoral', alpha=0.7) |
|
axes[0, 0].set_title('Component Failure Risk Analysis') |
|
axes[0, 0].set_ylabel('Failure Risk') |
|
axes[0, 0].tick_params(axis='x', rotation=45) |
|
axes[0, 0].grid(True, alpha=0.3) |
|
|
|
|
|
for bar in bars: |
|
height = bar.get_height() |
|
axes[0, 0].text(bar.get_x() + bar.get_width()/2., height, |
|
f'{height:.1%}', ha='center', va='bottom') |
|
|
|
|
|
axes[0, 1].hist(data['wear_level'], bins=20, alpha=0.7, color='skyblue', edgecolor='black') |
|
axes[0, 1].axvline(data['wear_level'].mean(), color='red', linestyle='--', |
|
label=f'Mean: {data["wear_level"].mean():.2f}') |
|
axes[0, 1].set_title('Component Wear Distribution') |
|
axes[0, 1].set_xlabel('Wear Level') |
|
axes[0, 1].set_ylabel('Frequency') |
|
axes[0, 1].legend() |
|
axes[0, 1].grid(True, alpha=0.3) |
|
|
|
|
|
scatter = axes[1, 0].scatter(data['max_temp'], data['wear_level'], |
|
c=data['failure_risk'], cmap='RdYlBu_r', alpha=0.6) |
|
axes[1, 0].set_xlabel('Maximum Temperature (°C)') |
|
axes[1, 0].set_ylabel('Wear Level') |
|
axes[1, 0].set_title('Temperature Impact on Component Wear') |
|
plt.colorbar(scatter, ax=axes[1, 0], label='Failure Risk') |
|
axes[1, 0].grid(True, alpha=0.3) |
|
|
|
|
|
maintenance_counts = data['maintenance_action'].value_counts() |
|
wedges, texts, autotexts = axes[1, 1].pie(maintenance_counts.values, |
|
labels=maintenance_counts.index, |
|
autopct='%1.1f%%', startangle=90) |
|
axes[1, 1].set_title('Maintenance Action Distribution') |
|
|
|
plt.tight_layout() |
|
return fig |
|
|
|
def generate_maintenance_schedule(self, data): |
|
"""Generate maintenance schedule recommendations""" |
|
schedule = [] |
|
|
|
for component in self.components.keys(): |
|
comp_data = data[data['component'] == component] |
|
|
|
if len(comp_data) == 0: |
|
continue |
|
|
|
avg_wear = comp_data['wear_level'].mean() |
|
failure_rate = comp_data['failure_risk'].mean() |
|
|
|
|
|
if failure_rate > 0.3: |
|
interval = "Every race weekend" |
|
elif failure_rate > 0.15: |
|
interval = "Every 2 race weekends" |
|
elif failure_rate > 0.05: |
|
interval = "Every 3 race weekends" |
|
else: |
|
interval = "Every 4 race weekends" |
|
|
|
|
|
if component in ['Engine', 'Gearbox']: |
|
priority = "High" |
|
elif component in ['Turbocharger', 'MGU-K', 'MGU-H']: |
|
priority = "Critical" |
|
else: |
|
priority = "Medium" |
|
|
|
schedule.append({ |
|
'Component': component, |
|
'Average Wear': f"{avg_wear:.1%}", |
|
'Failure Rate': f"{failure_rate:.1%}", |
|
'Recommended Interval': interval, |
|
'Priority': priority |
|
}) |
|
|
|
return pd.DataFrame(schedule) |
|
|
|
|
|
maintenance_system = F1PredictiveMaintenance() |
|
|
|
def analyze_maintenance_data(): |
|
"""Analyze maintenance data and train models""" |
|
|
|
data = maintenance_system.generate_maintenance_data(3000) |
|
|
|
|
|
failure_acc, wear_rmse, data_encoded = maintenance_system.train_models(data) |
|
|
|
|
|
fig = maintenance_system.create_maintenance_dashboard(data) |
|
|
|
|
|
schedule = maintenance_system.generate_maintenance_schedule(data) |
|
|
|
|
|
report = f""" |
|
## F1 Predictive Maintenance Analysis |
|
|
|
**Model Performance:** |
|
- Failure Prediction Accuracy: {failure_acc:.1%} |
|
- Wear Level RMSE: {wear_rmse:.3f} |
|
|
|
**Fleet Analysis:** |
|
- Total components analyzed: {len(data)} |
|
- Average wear level: {data['wear_level'].mean():.1%} |
|
- Components at risk: {(data['wear_level'] > 0.6).sum()} |
|
- High-priority maintenance: {(data['maintenance_action'] == 'Replace').sum()} |
|
|
|
**Risk Assessment:** |
|
- Highest risk component: {data.groupby('component')['failure_risk'].mean().idxmax()} |
|
- Most reliable component: {data.groupby('component')['failure_risk'].mean().idxmin()} |
|
- Critical temperature events: {(data['max_temp'] > 120).sum()} |
|
|
|
**Maintenance Recommendations:** |
|
- Immediate attention needed: {(data['wear_level'] > 0.8).sum()} components |
|
- Scheduled inspection: {(data['wear_level'] > 0.6).sum()} components |
|
- Monitoring required: {(data['wear_level'] > 0.4).sum()} components |
|
""" |
|
|
|
return fig, report, schedule |
|
|
|
def predict_component_maintenance(component, race_weekend, session_type, laps_completed, |
|
ambient_temp, track_temp, humidity, max_temp, avg_temp, |
|
vibration, load_factor, cycles_used, total_laps): |
|
"""Predict maintenance for specific component""" |
|
if not maintenance_system.is_trained: |
|
return "Please run the analysis first!", "", "" |
|
|
|
failure_risk, wear_level, maintenance_action = maintenance_system.predict_maintenance( |
|
component, race_weekend, session_type, laps_completed, |
|
ambient_temp, track_temp, humidity, max_temp, avg_temp, |
|
vibration, load_factor, cycles_used, total_laps |
|
) |
|
|
|
return failure_risk, wear_level, maintenance_action |
|
|
|
|
|
with gr.Blocks(title="F1 Predictive Maintenance System", theme=gr.themes.Soft()) as demo: |
|
gr.Markdown("# F1 Predictive Maintenance System") |
|
gr.Markdown("AI-powered predictive maintenance for Formula 1 components with failure prediction and wear analysis.") |
|
|
|
with gr.Tab("Maintenance Analysis"): |
|
gr.Markdown("### Analyze component reliability and maintenance requirements") |
|
analyze_btn = gr.Button("Analyze Fleet Data", variant="primary") |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=2): |
|
maintenance_plot = gr.Plot(label="Maintenance Dashboard") |
|
with gr.Column(scale=1): |
|
maintenance_report = gr.Markdown(label="Analysis Report") |
|
|
|
with gr.Row(): |
|
maintenance_schedule = gr.DataFrame(label="Maintenance Schedule", interactive=False) |
|
|
|
analyze_btn.click( |
|
analyze_maintenance_data, |
|
outputs=[maintenance_plot, maintenance_report, maintenance_schedule] |
|
) |
|
|
|
with gr.Tab("Component Prediction"): |
|
gr.Markdown("### Predict maintenance requirements for specific components") |
|
gr.Markdown("*Note: Run the analysis first to train the models*") |
|
|
|
with gr.Row(): |
|
with gr.Column(): |
|
gr.Markdown("**Component Information:**") |
|
component_select = gr.Dropdown( |
|
choices=list(maintenance_system.components.keys()), |
|
value="Engine", |
|
label="Component" |
|
) |
|
race_weekend_input = gr.Slider(1, 25, value=10, label="Race Weekend") |
|
session_type_select = gr.Dropdown( |
|
choices=["Practice", "Qualifying", "Race"], |
|
value="Race", |
|
label="Session Type" |
|
) |
|
laps_input = gr.Slider(10, 70, value=50, label="Laps Completed") |
|
|
|
gr.Markdown("**Operating Conditions:**") |
|
ambient_temp_input = gr.Slider(15, 35, value=25, label="Ambient Temperature (°C)") |
|
track_temp_input = gr.Slider(20, 60, value=40, label="Track Temperature (°C)") |
|
humidity_input = gr.Slider(40, 90, value=65, label="Humidity (%)") |
|
max_temp_input = gr.Slider(60, 200, value=100, label="Max Component Temperature (°C)") |
|
avg_temp_input = gr.Slider(50, 150, value=85, label="Average Temperature (°C)") |
|
|
|
with gr.Column(): |
|
gr.Markdown("**Component Usage:**") |
|
vibration_input = gr.Slider(0, 10, value=2, label="Vibration Level") |
|
load_factor_input = gr.Slider(0.5, 1.5, value=1.0, label="Load Factor") |
|
cycles_input = gr.Slider(0, 10, value=3, label="Cycles Used") |
|
total_laps_input = gr.Slider(0, 5000, value=1500, label="Total Laps") |
|
|
|
predict_btn = gr.Button("Predict Maintenance", variant="secondary") |
|
|
|
gr.Markdown("**Predictions:**") |
|
failure_risk_output = gr.Textbox(label="Failure Risk", interactive=False) |
|
wear_level_output = gr.Textbox(label="Wear Level", interactive=False) |
|
maintenance_action_output = gr.Textbox(label="Maintenance Action", interactive=False) |
|
|
|
predict_btn.click( |
|
predict_component_maintenance, |
|
inputs=[component_select, race_weekend_input, session_type_select, laps_input, |
|
ambient_temp_input, track_temp_input, humidity_input, max_temp_input, |
|
avg_temp_input, vibration_input, load_factor_input, cycles_input, total_laps_input], |
|
outputs=[failure_risk_output, wear_level_output, maintenance_action_output] |
|
) |
|
|
|
with gr.Tab("About"): |
|
gr.Markdown(""" |
|
## About This System |
|
|
|
This F1 Predictive Maintenance System uses advanced AI to predict component failures and optimize maintenance schedules: |
|
|
|
**Failure Prediction:** |
|
- Random Forest Classifier predicts component failure risk |
|
- Considers operating conditions, usage patterns, and environmental factors |
|
- Provides early warning for potential failures |
|
|
|
**Wear Analysis:** |
|
- Machine learning model predicts component wear levels |
|
- Accounts for temperature stress, vibration, and load factors |
|
- Enables proactive maintenance scheduling |
|
|
|
**Key Features:** |
|
- Real-time component health monitoring |
|
- Predictive maintenance recommendations |
|
- Temperature and environmental impact analysis |
|
- Maintenance schedule optimization |
|
- Component reliability assessment |
|
|
|
**Component Coverage:** |
|
- Engine and power unit components |
|
- Transmission and drivetrain |
|
- Hybrid energy systems (MGU-K, MGU-H) |
|
- Suspension and braking systems |
|
- Tires and consumables |
|
|
|
**Technical Implementation:** |
|
- Random Forest algorithms for robust predictions |
|
- Feature engineering for component-specific factors |
|
- Time-series analysis for wear progression |
|
- Risk assessment and priority classification |
|
|
|
**Racing Applications:** |
|
- Prevent costly race retirements |
|
- Optimize component allocation across seasons |
|
- Reduce unexpected failures during critical sessions |
|
- Enhance reliability through data-driven maintenance |
|
""") |
|
|
|
if __name__ == "__main__": |
|
demo.launch() |