File size: 26,089 Bytes
7b87ab1 8e83950 7b87ab1 8e83950 7b87ab1 8e83950 7b87ab1 8e83950 7b87ab1 8e83950 7b87ab1 f3ca752 7b87ab1 8e83950 7b87ab1 f3ca752 7b87ab1 f3ca752 7b87ab1 f3ca752 7b87ab1 8e83950 7b87ab1 8e83950 7b87ab1 f3ca752 7b87ab1 8e83950 7b87ab1 8e83950 f3ca752 7b87ab1 8e83950 7b87ab1 f3ca752 7b87ab1 f3ca752 7b87ab1 8e83950 7b87ab1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 |
import gradio as gr
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
from scipy.optimize import differential_evolution
import warnings
warnings.filterwarnings('ignore')
class F1AerodynamicPredictor:
def __init__(self):
self.model = RandomForestRegressor(n_estimators=100, random_state=42)
self.scaler = StandardScaler()
self.is_trained = False
self.current_data = None
self.data_source = "None"
self.feature_names = ['front_wing_angle', 'rear_wing_angle', 'ride_height',
'suspension_stiffness', 'downforce', 'drag_coefficient',
'track_temp', 'wind_speed', 'track_grip']
def generate_aero_data(self, num_samples=2000):
"""Generate realistic aerodynamic and setup data"""
np.random.seed(42)
# Car setup parameters
front_wing_angle = np.random.uniform(5, 25, num_samples) # degrees
rear_wing_angle = np.random.uniform(8, 35, num_samples) # degrees
ride_height = np.random.uniform(20, 80, num_samples) # mm
suspension_stiffness = np.random.uniform(50, 150, num_samples) # N/mm
# Aerodynamic parameters (derived from setup)
downforce = 800 + (front_wing_angle * 15) + (rear_wing_angle * 20) + np.random.normal(0, 50, num_samples)
drag_coefficient = 0.8 + (front_wing_angle * 0.02) + (rear_wing_angle * 0.025) + np.random.normal(0, 0.1, num_samples)
drag_coefficient = np.clip(drag_coefficient, 0.5, 2.0)
# Environmental conditions
track_temp = np.random.uniform(25, 45, num_samples) # °C
wind_speed = np.random.uniform(0, 15, num_samples) # m/s
track_grip = np.random.uniform(0.7, 1.0, num_samples) # coefficient
# Calculate lap time based on aerodynamic efficiency and setup
# Base lap time around 90 seconds, modified by aero efficiency
aero_efficiency = downforce / drag_coefficient
base_lap_time = 90
# Lap time calculation with realistic physics
lap_time = (base_lap_time -
(aero_efficiency - 800) * 0.01 + # Aero efficiency impact
(ride_height - 50) * 0.05 + # Ride height impact
(track_temp - 35) * 0.1 + # Temperature impact
wind_speed * 0.2 + # Wind resistance
(1 - track_grip) * 10 + # Grip impact
np.random.normal(0, 1, num_samples)) # Random variation
# Ensure realistic lap times
lap_time = np.clip(lap_time, 75, 110)
return pd.DataFrame({
'front_wing_angle': front_wing_angle,
'rear_wing_angle': rear_wing_angle,
'ride_height': ride_height,
'suspension_stiffness': suspension_stiffness,
'downforce': downforce,
'drag_coefficient': drag_coefficient,
'track_temp': track_temp,
'wind_speed': wind_speed,
'track_grip': track_grip,
'lap_time': lap_time
})
def validate_uploaded_data(self, df):
"""Validate uploaded data format and content"""
required_columns = self.feature_names + ['lap_time']
missing_columns = [col for col in required_columns if col not in df.columns]
if missing_columns:
return False, f"Missing required columns: {missing_columns}"
# Check for reasonable value ranges
validation_ranges = {
'front_wing_angle': (0, 50),
'rear_wing_angle': (0, 50),
'ride_height': (10, 150),
'suspension_stiffness': (10, 300),
'downforce': (200, 2000),
'drag_coefficient': (0.3, 3.0),
'track_temp': (5, 60),
'wind_speed': (0, 30),
'track_grip': (0.3, 1.2),
'lap_time': (60, 180)
}
validation_issues = []
for col, (min_val, max_val) in validation_ranges.items():
if col in df.columns:
out_of_range = df[(df[col] < min_val) | (df[col] > max_val)]
if len(out_of_range) > 0:
validation_issues.append(f"{col}: {len(out_of_range)} values out of range ({min_val}-{max_val})")
if validation_issues:
return False, f"Data validation issues: {'; '.join(validation_issues)}"
return True, "Data validation successful"
def load_user_data(self, file_path):
"""Load and validate user-uploaded data"""
try:
# Try to read the file
if file_path.name.endswith('.csv'):
df = pd.read_csv(file_path.name)
elif file_path.name.endswith(('.xlsx', '.xls')):
df = pd.read_excel(file_path.name)
else:
return None, "Unsupported file format. Please upload CSV or Excel files."
# Validate data
is_valid, message = self.validate_uploaded_data(df)
if not is_valid:
return None, message
# Store the data
self.current_data = df
self.data_source = "User uploaded"
return df, f"Successfully loaded {len(df)} records from uploaded file."
except Exception as e:
return None, f"Error loading file: {str(e)}"
def train_model(self, data):
"""Train the aerodynamic performance model"""
X = data[self.feature_names]
y = data['lap_time']
# Scale features
X_scaled = self.scaler.fit_transform(X)
# Train model
self.model.fit(X_scaled, y)
self.is_trained = True
# Calculate performance metrics
y_pred = self.model.predict(X_scaled)
r2 = r2_score(y, y_pred)
rmse = np.sqrt(mean_squared_error(y, y_pred))
return r2, rmse
def predict_lap_time(self, setup_params):
"""Predict lap time for given setup parameters"""
if not self.is_trained:
return None
# Prepare input
X = np.array([setup_params]).reshape(1, -1)
X_scaled = self.scaler.transform(X)
# Predict
lap_time = self.model.predict(X_scaled)[0]
return lap_time
def optimize_setup(self, track_conditions):
"""Optimize car setup for given track conditions"""
if not self.is_trained:
return None
track_temp, wind_speed, track_grip = track_conditions
def objective(params):
"""Objective function to minimize lap time"""
setup_params = list(params) + [track_temp, wind_speed, track_grip]
return self.predict_lap_time(setup_params)
# Define bounds for optimization (setup parameters only)
bounds = [
(5, 25), # front_wing_angle
(8, 35), # rear_wing_angle
(20, 80), # ride_height
(50, 150), # suspension_stiffness
(600, 1200), # downforce
(0.5, 2.0) # drag_coefficient
]
# Optimize using differential evolution
result = differential_evolution(objective, bounds, maxiter=100, seed=42)
optimal_setup = result.x
optimal_lap_time = result.fun
return optimal_setup, optimal_lap_time
def create_visualizations(self, data):
"""Create aerodynamic analysis visualizations"""
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
# Downforce vs Drag trade-off
aero_efficiency = data['downforce'] / data['drag_coefficient']
scatter = axes[0, 0].scatter(data['drag_coefficient'], data['downforce'],
c=data['lap_time'], cmap='RdYlBu_r', alpha=0.6)
axes[0, 0].set_xlabel('Drag Coefficient')
axes[0, 0].set_ylabel('Downforce (N)')
axes[0, 0].set_title('Downforce vs Drag Trade-off')
plt.colorbar(scatter, ax=axes[0, 0], label='Lap Time (s)')
axes[0, 0].grid(True, alpha=0.3)
# Wing angle correlation
axes[0, 1].scatter(data['front_wing_angle'], data['rear_wing_angle'],
c=data['lap_time'], cmap='RdYlBu_r', alpha=0.6)
axes[0, 1].set_xlabel('Front Wing Angle (°)')
axes[0, 1].set_ylabel('Rear Wing Angle (°)')
axes[0, 1].set_title('Wing Angle Configuration')
axes[0, 1].grid(True, alpha=0.3)
# Aerodynamic efficiency distribution
axes[1, 0].hist(aero_efficiency, bins=30, alpha=0.7, color='skyblue', edgecolor='black')
axes[1, 0].set_xlabel('Aerodynamic Efficiency (Downforce/Drag)')
axes[1, 0].set_ylabel('Frequency')
axes[1, 0].set_title('Aerodynamic Efficiency Distribution')
axes[1, 0].grid(True, alpha=0.3)
# Lap time vs environmental conditions
axes[1, 1].scatter(data['track_temp'], data['lap_time'], alpha=0.6, label='Track Temp')
axes[1, 1].set_xlabel('Track Temperature (°C)')
axes[1, 1].set_ylabel('Lap Time (s)')
axes[1, 1].set_title('Environmental Impact on Performance')
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
return fig
def compare_datasets(self, synthetic_data, user_data):
"""Compare user data with synthetic baseline"""
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
# Lap time distributions
axes[0, 0].hist(synthetic_data['lap_time'], bins=30, alpha=0.7,
label='Synthetic', color='blue', edgecolor='black')
axes[0, 0].hist(user_data['lap_time'], bins=30, alpha=0.7,
label='User Data', color='red', edgecolor='black')
axes[0, 0].set_xlabel('Lap Time (s)')
axes[0, 0].set_ylabel('Frequency')
axes[0, 0].set_title('Lap Time Distribution Comparison')
axes[0, 0].legend()
axes[0, 0].grid(True, alpha=0.3)
# Aerodynamic efficiency comparison
synthetic_eff = synthetic_data['downforce'] / synthetic_data['drag_coefficient']
user_eff = user_data['downforce'] / user_data['drag_coefficient']
axes[0, 1].scatter(synthetic_data['drag_coefficient'], synthetic_data['downforce'],
alpha=0.5, label='Synthetic', color='blue')
axes[0, 1].scatter(user_data['drag_coefficient'], user_data['downforce'],
alpha=0.5, label='User Data', color='red')
axes[0, 1].set_xlabel('Drag Coefficient')
axes[0, 1].set_ylabel('Downforce (N)')
axes[0, 1].set_title('Aerodynamic Trade-off Comparison')
axes[0, 1].legend()
axes[0, 1].grid(True, alpha=0.3)
# Wing angle comparison
axes[1, 0].scatter(synthetic_data['front_wing_angle'], synthetic_data['rear_wing_angle'],
alpha=0.5, label='Synthetic', color='blue')
axes[1, 0].scatter(user_data['front_wing_angle'], user_data['rear_wing_angle'],
alpha=0.5, label='User Data', color='red')
axes[1, 0].set_xlabel('Front Wing Angle (°)')
axes[1, 0].set_ylabel('Rear Wing Angle (°)')
axes[1, 0].set_title('Wing Configuration Comparison')
axes[1, 0].legend()
axes[1, 0].grid(True, alpha=0.3)
# Performance correlation
axes[1, 1].scatter(synthetic_eff, synthetic_data['lap_time'],
alpha=0.5, label='Synthetic', color='blue')
axes[1, 1].scatter(user_eff, user_data['lap_time'],
alpha=0.5, label='User Data', color='red')
axes[1, 1].set_xlabel('Aerodynamic Efficiency')
axes[1, 1].set_ylabel('Lap Time (s)')
axes[1, 1].set_title('Efficiency vs Performance')
axes[1, 1].legend()
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
return fig
# Initialize the predictor
predictor = F1AerodynamicPredictor()
def analyze_aerodynamics():
"""Main aerodynamic analysis function"""
# Generate data
data = predictor.generate_aero_data(2000)
# Train model
r2, rmse = predictor.train_model(data)
# Create visualizations
fig = predictor.create_visualizations(data)
# Generate report
report = f"""
## F1 Aerodynamic Performance Analysis (Synthetic Data)
**Model Performance:**
- R² Score: {r2:.3f}
- RMSE: {rmse:.3f} seconds
**Dataset Statistics:**
- Total configurations analyzed: {len(data)}
- Fastest lap time: {data['lap_time'].min():.2f}s
- Slowest lap time: {data['lap_time'].max():.2f}s
- Average lap time: {data['lap_time'].mean():.2f}s
**Aerodynamic Insights:**
- Average downforce: {data['downforce'].mean():.0f}N
- Average drag coefficient: {data['drag_coefficient'].mean():.3f}
- Best aero efficiency: {(data['downforce'] / data['drag_coefficient']).max():.1f}
**Optimal Ranges:**
- Front wing: {data['front_wing_angle'].quantile(0.1):.1f}° - {data['front_wing_angle'].quantile(0.9):.1f}°
- Rear wing: {data['rear_wing_angle'].quantile(0.1):.1f}° - {data['rear_wing_angle'].quantile(0.9):.1f}°
- Ride height: {data['ride_height'].quantile(0.1):.1f}mm - {data['ride_height'].quantile(0.9):.1f}mm
"""
return fig, report
def upload_and_analyze_data(file):
"""Handle file upload and analysis"""
if file is None:
return None, "Please upload a data file.", None
# Load user data
user_data, message = predictor.load_user_data(file)
if user_data is None:
return None, message, None
# Train model on user data
r2, rmse = predictor.train_model(user_data)
# Create visualizations
fig = predictor.create_visualizations(user_data)
# Generate report
report = f"""
## F1 Aerodynamic Performance Analysis (User Data)
**Data Load Status:** {message}
**Model Performance:**
- R² Score: {r2:.3f}
- RMSE: {rmse:.3f} seconds
**Dataset Statistics:**
- Total configurations analyzed: {len(user_data)}
- Fastest lap time: {user_data['lap_time'].min():.2f}s
- Slowest lap time: {user_data['lap_time'].max():.2f}s
- Average lap time: {user_data['lap_time'].mean():.2f}s
**Aerodynamic Insights:**
- Average downforce: {user_data['downforce'].mean():.0f}N
- Average drag coefficient: {user_data['drag_coefficient'].mean():.3f}
- Best aero efficiency: {(user_data['downforce'] / user_data['drag_coefficient']).max():.1f}
**Data Quality Assessment:**
- Missing values: {user_data.isnull().sum().sum()}
- Duplicate records: {user_data.duplicated().sum()}
- Data range validation: Passed
"""
return fig, report, user_data
def compare_data_sources():
"""Compare user data with synthetic baseline"""
if predictor.current_data is None:
return None, "Please upload data first to enable comparison."
# Generate synthetic data for comparison
synthetic_data = predictor.generate_aero_data(len(predictor.current_data))
# Create comparison visualization
fig = predictor.compare_datasets(synthetic_data, predictor.current_data)
# Generate comparison report
synthetic_avg = synthetic_data['lap_time'].mean()
user_avg = predictor.current_data['lap_time'].mean()
report = f"""
## Data Comparison Report
**Performance Comparison:**
- Synthetic Data Average Lap Time: {synthetic_avg:.2f}s
- User Data Average Lap Time: {user_avg:.2f}s
- Difference: {user_avg - synthetic_avg:.2f}s
**Setup Characteristics:**
- Synthetic wing angles are more conservative
- User data shows {'more aggressive' if user_avg < synthetic_avg else 'more conservative'} setup approach
- Aerodynamic efficiency patterns {'align well' if abs(user_avg - synthetic_avg) < 2 else 'show significant differences'}
**Recommendations:**
- {'Your data suggests more aggressive setups than baseline' if user_avg < synthetic_avg else 'Consider more aggressive aerodynamic configurations'}
- Validate setup ranges against your specific track conditions
- Use comparison insights to refine optimization parameters
"""
return fig, report
def predict_performance(front_wing, rear_wing, ride_height, suspension, downforce, drag_coeff, track_temp, wind_speed, track_grip):
"""Predict lap time for given setup"""
if not predictor.is_trained:
return "Please run the analysis first to train the model!"
setup_params = [front_wing, rear_wing, ride_height, suspension, downforce, drag_coeff, track_temp, wind_speed, track_grip]
lap_time = predictor.predict_lap_time(setup_params)
data_source_note = f"(Model trained on: {predictor.data_source})"
return f"Predicted Lap Time: {lap_time:.3f} seconds {data_source_note}"
def optimize_car_setup(track_temp, wind_speed, track_grip):
"""Optimize car setup for given conditions"""
if not predictor.is_trained:
return "Please run the analysis first to train the model!"
track_conditions = [track_temp, wind_speed, track_grip]
result = predictor.optimize_setup(track_conditions)
if result is None:
return "Optimization failed"
optimal_setup, optimal_lap_time = result
setup_report = f"""
## Optimal Car Setup
**Predicted Lap Time: {optimal_lap_time:.3f} seconds**
*(Model trained on: {predictor.data_source})*
**Optimal Configuration:**
- Front Wing Angle: {optimal_setup[0]:.1f}°
- Rear Wing Angle: {optimal_setup[1]:.1f}°
- Ride Height: {optimal_setup[2]:.1f}mm
- Suspension Stiffness: {optimal_setup[3]:.1f} N/mm
- Target Downforce: {optimal_setup[4]:.0f}N
- Target Drag Coefficient: {optimal_setup[5]:.3f}
**Track Conditions:**
- Track Temperature: {track_temp}°C
- Wind Speed: {wind_speed} m/s
- Track Grip: {track_grip}
"""
return setup_report
def create_sample_data():
"""Create sample data file for download"""
sample_data = predictor.generate_aero_data(100)
return sample_data.to_csv(index=False)
# Create Gradio interface
with gr.Blocks(title="F1 Aerodynamic Performance Predictor", theme=gr.themes.Soft()) as demo:
gr.Markdown("# F1 Aerodynamic Performance Predictor")
gr.Markdown("AI-powered aerodynamic analysis and setup optimization for Formula 1 racing.")
with gr.Tab("Synthetic Data Analysis"):
gr.Markdown("### Analyze synthetic aerodynamic performance data")
analyze_btn = gr.Button("🔍 Analyze Synthetic Data", variant="primary")
with gr.Row():
with gr.Column(scale=2):
aero_plot = gr.Plot(label="Aerodynamic Analysis")
with gr.Column(scale=1):
aero_report = gr.Markdown(label="Analysis Report")
analyze_btn.click(
analyze_aerodynamics,
outputs=[aero_plot, aero_report]
)
with gr.Tab("Upload & Analyze Data"):
gr.Markdown("### Upload your own F1 data for analysis")
gr.Markdown("**Required columns:** front_wing_angle, rear_wing_angle, ride_height, suspension_stiffness, downforce, drag_coefficient, track_temp, wind_speed, track_grip, lap_time")
with gr.Row():
with gr.Column():
file_upload = gr.File(
label="Upload CSV or Excel file",
file_types=[".csv", ".xlsx", ".xls"]
)
sample_btn = gr.Button("Download Sample Data Format", variant="secondary")
sample_file = gr.File(label="Sample Data", visible=False)
upload_btn = gr.Button("Analyze Uploaded Data", variant="primary")
with gr.Column():
upload_status = gr.Markdown("No file uploaded yet.")
with gr.Row():
with gr.Column(scale=2):
upload_plot = gr.Plot(label="Data Analysis")
with gr.Column(scale=1):
upload_report = gr.Markdown(label="Analysis Report")
# Comparison section
gr.Markdown("### Compare with Synthetic Baseline")
compare_btn = gr.Button("Compare Data Sources", variant="secondary")
with gr.Row():
with gr.Column(scale=2):
comparison_plot = gr.Plot(label="Data Comparison")
with gr.Column(scale=1):
comparison_report = gr.Markdown(label="Comparison Report")
# Event handlers
sample_btn.click(
create_sample_data,
outputs=[sample_file]
)
upload_btn.click(
upload_and_analyze_data,
inputs=[file_upload],
outputs=[upload_plot, upload_report, upload_status]
)
compare_btn.click(
compare_data_sources,
outputs=[comparison_plot, comparison_report]
)
with gr.Tab("Performance Prediction"):
gr.Markdown("### Predict lap time for specific setup")
gr.Markdown("*Note: Train the model first using synthetic or uploaded data*")
with gr.Row():
with gr.Column():
gr.Markdown("**Car Setup Parameters:**")
front_wing_input = gr.Slider(5, 25, value=15, label="Front Wing Angle (°)")
rear_wing_input = gr.Slider(8, 35, value=20, label="Rear Wing Angle (°)")
ride_height_input = gr.Slider(20, 80, value=50, label="Ride Height (mm)")
suspension_input = gr.Slider(50, 150, value=100, label="Suspension Stiffness (N/mm)")
downforce_input = gr.Slider(600, 1200, value=900, label="Downforce (N)")
drag_input = gr.Slider(0.5, 2.0, value=1.0, label="Drag Coefficient")
with gr.Column():
gr.Markdown("**Track Conditions:**")
track_temp_input = gr.Slider(25, 45, value=35, label="Track Temperature (°C)")
wind_speed_input = gr.Slider(0, 15, value=5, label="Wind Speed (m/s)")
track_grip_input = gr.Slider(0.7, 1.0, value=0.85, label="Track Grip")
predict_btn = gr.Button("🎯 Predict Lap Time", variant="secondary")
lap_time_output = gr.Textbox(label="Lap Time Prediction", interactive=False)
predict_btn.click(
predict_performance,
inputs=[front_wing_input, rear_wing_input, ride_height_input, suspension_input,
downforce_input, drag_input, track_temp_input, wind_speed_input, track_grip_input],
outputs=[lap_time_output]
)
with gr.Tab("Setup Optimization"):
gr.Markdown("### Optimize car setup for track conditions")
gr.Markdown("*Uses genetic algorithm to find optimal aerodynamic configuration*")
with gr.Row():
with gr.Column():
gr.Markdown("**Track Conditions:**")
opt_track_temp = gr.Slider(25, 45, value=35, label="Track Temperature (°C)")
opt_wind_speed = gr.Slider(0, 15, value=5, label="Wind Speed (m/s)")
opt_track_grip = gr.Slider(0.7, 1.0, value=0.85, label="Track Grip")
optimize_btn = gr.Button("🔧 Optimize Setup", variant="primary")
with gr.Column():
optimization_output = gr.Markdown(label="Optimization Results")
optimize_btn.click(
optimize_car_setup,
inputs=[opt_track_temp, opt_wind_speed, opt_track_grip],
outputs=[optimization_output]
)
with gr.Tab("About"):
gr.Markdown("""
## About This Enhanced Tool
This F1 Aerodynamic Performance Predictor now supports both synthetic and real data analysis:
**Dual Data Sources:**
- **Synthetic Data**: Realistic simulated F1 aerodynamic data for learning and experimentation
- **User Data**: Upload your own telemetry, test results, or historical performance data
**Data Upload Features:**
- CSV and Excel file support
- Automatic data validation and quality checks
- Sample data template download
- Comparison analysis between your data and synthetic baseline
**Enhanced Analysis:**
- Model training on real or synthetic data
- Data quality assessment and validation
- Performance comparison between different datasets
- Track which data source was used for predictions
**Setup Optimization:**
- Uses Differential Evolution algorithm for global optimization
- Adapts to patterns in your specific data
- Provides data-source-aware recommendations
**Required Data Format:**
Your uploaded data should include these columns:
- front_wing_angle, rear_wing_angle, ride_height
- suspension_stiffness, downforce, drag_coefficient
- track_temp, wind_speed, track_grip, lap_time
**Professional Applications:**
- Validate simulation models against real telemetry
- Identify setup trends and patterns in your data
- Optimize configurations for specific track conditions
- Compare your team's approach with industry baselines
""")
if __name__ == "__main__":
demo.launch() |