CCockrum commited on
Commit
7b87ab1
·
verified ·
1 Parent(s): d35b005

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +400 -0
app.py ADDED
@@ -0,0 +1,400 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 RandomForestRegressor
6
+ from sklearn.preprocessing import StandardScaler
7
+ from sklearn.metrics import mean_squared_error, r2_score
8
+ from scipy.optimize import differential_evolution
9
+ import warnings
10
+ warnings.filterwarnings('ignore')
11
+
12
+ class F1AerodynamicPredictor:
13
+ def __init__(self):
14
+ self.model = RandomForestRegressor(n_estimators=100, random_state=42)
15
+ self.scaler = StandardScaler()
16
+ self.is_trained = False
17
+ self.feature_names = ['front_wing_angle', 'rear_wing_angle', 'ride_height',
18
+ 'suspension_stiffness', 'downforce', 'drag_coefficient',
19
+ 'track_temp', 'wind_speed', 'track_grip']
20
+
21
+ def generate_aero_data(self, num_samples=2000):
22
+ """Generate realistic aerodynamic and setup data"""
23
+ np.random.seed(42)
24
+
25
+ # Car setup parameters
26
+ front_wing_angle = np.random.uniform(5, 25, num_samples) # degrees
27
+ rear_wing_angle = np.random.uniform(8, 35, num_samples) # degrees
28
+ ride_height = np.random.uniform(20, 80, num_samples) # mm
29
+ suspension_stiffness = np.random.uniform(50, 150, num_samples) # N/mm
30
+
31
+ # Aerodynamic parameters (derived from setup)
32
+ downforce = 800 + (front_wing_angle * 15) + (rear_wing_angle * 20) + np.random.normal(0, 50, num_samples)
33
+ drag_coefficient = 0.8 + (front_wing_angle * 0.02) + (rear_wing_angle * 0.025) + np.random.normal(0, 0.1, num_samples)
34
+ drag_coefficient = np.clip(drag_coefficient, 0.5, 2.0)
35
+
36
+ # Environmental conditions
37
+ track_temp = np.random.uniform(25, 45, num_samples) # °C
38
+ wind_speed = np.random.uniform(0, 15, num_samples) # m/s
39
+ track_grip = np.random.uniform(0.7, 1.0, num_samples) # coefficient
40
+
41
+ # Calculate lap time based on aerodynamic efficiency and setup
42
+ # Base lap time around 90 seconds, modified by aero efficiency
43
+ aero_efficiency = downforce / drag_coefficient
44
+ base_lap_time = 90
45
+
46
+ # Lap time calculation with realistic physics
47
+ lap_time = (base_lap_time -
48
+ (aero_efficiency - 800) * 0.01 + # Aero efficiency impact
49
+ (ride_height - 50) * 0.05 + # Ride height impact
50
+ (track_temp - 35) * 0.1 + # Temperature impact
51
+ wind_speed * 0.2 + # Wind resistance
52
+ (1 - track_grip) * 10 + # Grip impact
53
+ np.random.normal(0, 1, num_samples)) # Random variation
54
+
55
+ # Ensure realistic lap times
56
+ lap_time = np.clip(lap_time, 75, 110)
57
+
58
+ return pd.DataFrame({
59
+ 'front_wing_angle': front_wing_angle,
60
+ 'rear_wing_angle': rear_wing_angle,
61
+ 'ride_height': ride_height,
62
+ 'suspension_stiffness': suspension_stiffness,
63
+ 'downforce': downforce,
64
+ 'drag_coefficient': drag_coefficient,
65
+ 'track_temp': track_temp,
66
+ 'wind_speed': wind_speed,
67
+ 'track_grip': track_grip,
68
+ 'lap_time': lap_time
69
+ })
70
+
71
+ def train_model(self, data):
72
+ """Train the aerodynamic performance model"""
73
+ X = data[self.feature_names]
74
+ y = data['lap_time']
75
+
76
+ # Scale features
77
+ X_scaled = self.scaler.fit_transform(X)
78
+
79
+ # Train model
80
+ self.model.fit(X_scaled, y)
81
+ self.is_trained = True
82
+
83
+ # Calculate performance metrics
84
+ y_pred = self.model.predict(X_scaled)
85
+ r2 = r2_score(y, y_pred)
86
+ rmse = np.sqrt(mean_squared_error(y, y_pred))
87
+
88
+ return r2, rmse
89
+
90
+ def predict_lap_time(self, setup_params):
91
+ """Predict lap time for given setup parameters"""
92
+ if not self.is_trained:
93
+ return None
94
+
95
+ # Prepare input
96
+ X = np.array([setup_params]).reshape(1, -1)
97
+ X_scaled = self.scaler.transform(X)
98
+
99
+ # Predict
100
+ lap_time = self.model.predict(X_scaled)[0]
101
+ return lap_time
102
+
103
+ def optimize_setup(self, track_conditions):
104
+ """Optimize car setup for given track conditions"""
105
+ if not self.is_trained:
106
+ return None
107
+
108
+ track_temp, wind_speed, track_grip = track_conditions
109
+
110
+ def objective(params):
111
+ """Objective function to minimize lap time"""
112
+ setup_params = list(params) + [track_temp, wind_speed, track_grip]
113
+ return self.predict_lap_time(setup_params)
114
+
115
+ # Define bounds for optimization (setup parameters only)
116
+ bounds = [
117
+ (5, 25), # front_wing_angle
118
+ (8, 35), # rear_wing_angle
119
+ (20, 80), # ride_height
120
+ (50, 150), # suspension_stiffness
121
+ (600, 1200), # downforce
122
+ (0.5, 2.0) # drag_coefficient
123
+ ]
124
+
125
+ # Optimize using differential evolution
126
+ result = differential_evolution(objective, bounds, maxiter=100, seed=42)
127
+
128
+ optimal_setup = result.x
129
+ optimal_lap_time = result.fun
130
+
131
+ return optimal_setup, optimal_lap_time
132
+
133
+ def analyze_sensitivity(self, base_setup, track_conditions):
134
+ """Analyze sensitivity of lap time to setup changes"""
135
+ if not self.is_trained:
136
+ return None, None
137
+
138
+ # Base lap time
139
+ base_params = list(base_setup) + list(track_conditions)
140
+ base_lap_time = self.predict_lap_time(base_params)
141
+
142
+ # Analyze each parameter
143
+ sensitivity_data = []
144
+ param_names = ['Front Wing', 'Rear Wing', 'Ride Height', 'Suspension', 'Downforce', 'Drag Coeff']
145
+
146
+ for i, param_name in enumerate(param_names):
147
+ # Test parameter variations
148
+ variations = np.linspace(0.8, 1.2, 21) # ±20% variation
149
+ lap_times = []
150
+
151
+ for var in variations:
152
+ test_setup = base_setup.copy()
153
+ test_setup[i] *= var
154
+ test_params = list(test_setup) + list(track_conditions)
155
+ lap_time = self.predict_lap_time(test_params)
156
+ lap_times.append(lap_time)
157
+
158
+ sensitivity_data.append({
159
+ 'parameter': param_name,
160
+ 'variations': variations,
161
+ 'lap_times': lap_times,
162
+ 'sensitivity': np.std(lap_times)
163
+ })
164
+
165
+ return sensitivity_data, base_lap_time
166
+
167
+ def create_visualizations(self, data):
168
+ """Create aerodynamic analysis visualizations"""
169
+ fig, axes = plt.subplots(2, 2, figsize=(15, 12))
170
+
171
+ # Downforce vs Drag trade-off
172
+ aero_efficiency = data['downforce'] / data['drag_coefficient']
173
+ scatter = axes[0, 0].scatter(data['drag_coefficient'], data['downforce'],
174
+ c=data['lap_time'], cmap='RdYlBu_r', alpha=0.6)
175
+ axes[0, 0].set_xlabel('Drag Coefficient')
176
+ axes[0, 0].set_ylabel('Downforce (N)')
177
+ axes[0, 0].set_title('Downforce vs Drag Trade-off')
178
+ plt.colorbar(scatter, ax=axes[0, 0], label='Lap Time (s)')
179
+ axes[0, 0].grid(True, alpha=0.3)
180
+
181
+ # Wing angle correlation
182
+ axes[0, 1].scatter(data['front_wing_angle'], data['rear_wing_angle'],
183
+ c=data['lap_time'], cmap='RdYlBu_r', alpha=0.6)
184
+ axes[0, 1].set_xlabel('Front Wing Angle (°)')
185
+ axes[0, 1].set_ylabel('Rear Wing Angle (°)')
186
+ axes[0, 1].set_title('Wing Angle Configuration')
187
+ axes[0, 1].grid(True, alpha=0.3)
188
+
189
+ # Aerodynamic efficiency distribution
190
+ axes[1, 0].hist(aero_efficiency, bins=30, alpha=0.7, color='skyblue', edgecolor='black')
191
+ axes[1, 0].set_xlabel('Aerodynamic Efficiency (Downforce/Drag)')
192
+ axes[1, 0].set_ylabel('Frequency')
193
+ axes[1, 0].set_title('Aerodynamic Efficiency Distribution')
194
+ axes[1, 0].grid(True, alpha=0.3)
195
+
196
+ # Lap time vs environmental conditions
197
+ axes[1, 1].scatter(data['track_temp'], data['lap_time'], alpha=0.6, label='Track Temp')
198
+ axes[1, 1].set_xlabel('Track Temperature (°C)')
199
+ axes[1, 1].set_ylabel('Lap Time (s)')
200
+ axes[1, 1].set_title('Environmental Impact on Performance')
201
+ axes[1, 1].grid(True, alpha=0.3)
202
+
203
+ plt.tight_layout()
204
+ return fig
205
+
206
+ # Initialize the predictor
207
+ predictor = F1AerodynamicPredictor()
208
+
209
+ def analyze_aerodynamics():
210
+ """Main aerodynamic analysis function"""
211
+ # Generate data
212
+ data = predictor.generate_aero_data(2000)
213
+
214
+ # Train model
215
+ r2, rmse = predictor.train_model(data)
216
+
217
+ # Create visualizations
218
+ fig = predictor.create_visualizations(data)
219
+
220
+ # Generate report
221
+ report = f"""
222
+ ## F1 Aerodynamic Performance Analysis
223
+
224
+ **Model Performance:**
225
+ - R² Score: {r2:.3f}
226
+ - RMSE: {rmse:.3f} seconds
227
+
228
+ **Dataset Statistics:**
229
+ - Total configurations analyzed: {len(data)}
230
+ - Fastest lap time: {data['lap_time'].min():.2f}s
231
+ - Slowest lap time: {data['lap_time'].max():.2f}s
232
+ - Average lap time: {data['lap_time'].mean():.2f}s
233
+
234
+ **Aerodynamic Insights:**
235
+ - Average downforce: {data['downforce'].mean():.0f}N
236
+ - Average drag coefficient: {data['drag_coefficient'].mean():.3f}
237
+ - Best aero efficiency: {(data['downforce'] / data['drag_coefficient']).max():.1f}
238
+
239
+ **Optimal Ranges:**
240
+ - Front wing: {data['front_wing_angle'].quantile(0.1):.1f}° - {data['front_wing_angle'].quantile(0.9):.1f}°
241
+ - Rear wing: {data['rear_wing_angle'].quantile(0.1):.1f}° - {data['rear_wing_angle'].quantile(0.9):.1f}°
242
+ - Ride height: {data['ride_height'].quantile(0.1):.1f}mm - {data['ride_height'].quantile(0.9):.1f}mm
243
+ """
244
+
245
+ return fig, report
246
+
247
+ def predict_performance(front_wing, rear_wing, ride_height, suspension, downforce, drag_coeff, track_temp, wind_speed, track_grip):
248
+ """Predict lap time for given setup"""
249
+ if not predictor.is_trained:
250
+ return "⚠️ Please run the analysis first to train the model!"
251
+
252
+ setup_params = [front_wing, rear_wing, ride_height, suspension, downforce, drag_coeff, track_temp, wind_speed, track_grip]
253
+ lap_time = predictor.predict_lap_time(setup_params)
254
+
255
+ return f"🏁 Predicted Lap Time: {lap_time:.3f} seconds"
256
+
257
+ def optimize_car_setup(track_temp, wind_speed, track_grip):
258
+ """Optimize car setup for given conditions"""
259
+ if not predictor.is_trained:
260
+ return "⚠️ Please run the analysis first to train the model!"
261
+
262
+ track_conditions = [track_temp, wind_speed, track_grip]
263
+ result = predictor.optimize_setup(track_conditions)
264
+
265
+ if result is None:
266
+ return "❌ Optimization failed"
267
+
268
+ optimal_setup, optimal_lap_time = result
269
+
270
+ setup_report = f"""
271
+ ## 🏆 Optimal Car Setup
272
+
273
+ **Predicted Lap Time: {optimal_lap_time:.3f} seconds**
274
+
275
+ **Optimal Configuration:**
276
+ - Front Wing Angle: {optimal_setup[0]:.1f}°
277
+ - Rear Wing Angle: {optimal_setup[1]:.1f}°
278
+ - Ride Height: {optimal_setup[2]:.1f}mm
279
+ - Suspension Stiffness: {optimal_setup[3]:.1f} N/mm
280
+ - Target Downforce: {optimal_setup[4]:.0f}N
281
+ - Target Drag Coefficient: {optimal_setup[5]:.3f}
282
+
283
+ **Track Conditions:**
284
+ - Track Temperature: {track_temp}°C
285
+ - Wind Speed: {wind_speed} m/s
286
+ - Track Grip: {track_grip}
287
+ """
288
+
289
+ return setup_report
290
+
291
+ # Create Gradio interface
292
+ with gr.Blocks(title="F1 Aerodynamic Performance Predictor", theme=gr.themes.Soft()) as demo:
293
+ gr.Markdown("# 🏎️ F1 Aerodynamic Performance Predictor")
294
+ gr.Markdown("AI-powered aerodynamic analysis and setup optimization for Formula 1 racing.")
295
+
296
+ with gr.Tab("📊 Aerodynamic Analysis"):
297
+ gr.Markdown("### Analyze aerodynamic performance data")
298
+ analyze_btn = gr.Button("🔍 Analyze Aerodynamics", variant="primary")
299
+
300
+ with gr.Row():
301
+ with gr.Column(scale=2):
302
+ aero_plot = gr.Plot(label="Aerodynamic Analysis")
303
+ with gr.Column(scale=1):
304
+ aero_report = gr.Markdown(label="Analysis Report")
305
+
306
+ analyze_btn.click(
307
+ analyze_aerodynamics,
308
+ outputs=[aero_plot, aero_report]
309
+ )
310
+
311
+ with gr.Tab("🎯 Performance Prediction"):
312
+ gr.Markdown("### Predict lap time for specific setup")
313
+ gr.Markdown("*Note: Run the analysis first to train the model*")
314
+
315
+ with gr.Row():
316
+ with gr.Column():
317
+ gr.Markdown("**Car Setup Parameters:**")
318
+ front_wing_input = gr.Slider(5, 25, value=15, label="Front Wing Angle (°)")
319
+ rear_wing_input = gr.Slider(8, 35, value=20, label="Rear Wing Angle (°)")
320
+ ride_height_input = gr.Slider(20, 80, value=50, label="Ride Height (mm)")
321
+ suspension_input = gr.Slider(50, 150, value=100, label="Suspension Stiffness (N/mm)")
322
+ downforce_input = gr.Slider(600, 1200, value=900, label="Downforce (N)")
323
+ drag_input = gr.Slider(0.5, 2.0, value=1.0, label="Drag Coefficient")
324
+
325
+ with gr.Column():
326
+ gr.Markdown("**Track Conditions:**")
327
+ track_temp_input = gr.Slider(25, 45, value=35, label="Track Temperature (°C)")
328
+ wind_speed_input = gr.Slider(0, 15, value=5, label="Wind Speed (m/s)")
329
+ track_grip_input = gr.Slider(0.7, 1.0, value=0.85, label="Track Grip")
330
+
331
+ predict_btn = gr.Button("🎯 Predict Lap Time", variant="secondary")
332
+
333
+ lap_time_output = gr.Textbox(label="Lap Time Prediction", interactive=False)
334
+
335
+ predict_btn.click(
336
+ predict_performance,
337
+ inputs=[front_wing_input, rear_wing_input, ride_height_input, suspension_input,
338
+ downforce_input, drag_input, track_temp_input, wind_speed_input, track_grip_input],
339
+ outputs=[lap_time_output]
340
+ )
341
+
342
+ with gr.Tab("🏆 Setup Optimization"):
343
+ gr.Markdown("### Optimize car setup for track conditions")
344
+ gr.Markdown("*Uses genetic algorithm to find optimal aerodynamic configuration*")
345
+
346
+ with gr.Row():
347
+ with gr.Column():
348
+ gr.Markdown("**Track Conditions:**")
349
+ opt_track_temp = gr.Slider(25, 45, value=35, label="Track Temperature (°C)")
350
+ opt_wind_speed = gr.Slider(0, 15, value=5, label="Wind Speed (m/s)")
351
+ opt_track_grip = gr.Slider(0.7, 1.0, value=0.85, label="Track Grip")
352
+
353
+ optimize_btn = gr.Button("🔧 Optimize Setup", variant="primary")
354
+
355
+ with gr.Column():
356
+ optimization_output = gr.Markdown(label="Optimization Results")
357
+
358
+ optimize_btn.click(
359
+ optimize_car_setup,
360
+ inputs=[opt_track_temp, opt_wind_speed, opt_track_grip],
361
+ outputs=[optimization_output]
362
+ )
363
+
364
+ with gr.Tab("ℹ️ About"):
365
+ gr.Markdown("""
366
+ ## About This Tool
367
+
368
+ This F1 Aerodynamic Performance Predictor uses advanced machine learning and optimization techniques:
369
+
370
+ **🎯 Performance Prediction:**
371
+ - Random Forest model predicts lap times based on car setup and track conditions
372
+ - Considers aerodynamic efficiency, wing configurations, and environmental factors
373
+ - Trained on realistic F1 aerodynamic data
374
+
375
+ **🔧 Setup Optimization:**
376
+ - Uses Differential Evolution algorithm to find optimal car configurations
377
+ - Balances downforce vs drag for maximum performance
378
+ - Considers track-specific conditions for tailored setups
379
+
380
+ **📊 Key Features:**
381
+ - Aerodynamic efficiency analysis (downforce/drag ratio)
382
+ - Wing angle optimization for different track types
383
+ - Environmental impact assessment (temperature, wind, grip)
384
+ - Sensitivity analysis for setup parameters
385
+
386
+ **🏗️ Technical Implementation:**
387
+ - Random Forest Regressor for non-linear relationships
388
+ - Differential Evolution for global optimization
389
+ - StandardScaler for feature normalization
390
+ - Advanced visualization of aerodynamic trade-offs
391
+
392
+ **🏁 Racing Applications:**
393
+ - Pre-race setup optimization
394
+ - Strategy planning for different track conditions
395
+ - Understanding aerodynamic trade-offs
396
+ - Performance prediction for qualifying and race scenarios
397
+ """)
398
+
399
+ if __name__ == "__main__":
400
+ demo.launch()