|
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) |
|
|
|
|
|
front_wing_angle = np.random.uniform(5, 25, num_samples) |
|
rear_wing_angle = np.random.uniform(8, 35, num_samples) |
|
ride_height = np.random.uniform(20, 80, num_samples) |
|
suspension_stiffness = np.random.uniform(50, 150, num_samples) |
|
|
|
|
|
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) |
|
|
|
|
|
track_temp = np.random.uniform(25, 45, num_samples) |
|
wind_speed = np.random.uniform(0, 15, num_samples) |
|
track_grip = np.random.uniform(0.7, 1.0, num_samples) |
|
|
|
|
|
|
|
aero_efficiency = downforce / drag_coefficient |
|
base_lap_time = 90 |
|
|
|
|
|
lap_time = (base_lap_time - |
|
(aero_efficiency - 800) * 0.01 + |
|
(ride_height - 50) * 0.05 + |
|
(track_temp - 35) * 0.1 + |
|
wind_speed * 0.2 + |
|
(1 - track_grip) * 10 + |
|
np.random.normal(0, 1, num_samples)) |
|
|
|
|
|
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}" |
|
|
|
|
|
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: |
|
|
|
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." |
|
|
|
|
|
is_valid, message = self.validate_uploaded_data(df) |
|
if not is_valid: |
|
return None, message |
|
|
|
|
|
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'] |
|
|
|
|
|
X_scaled = self.scaler.fit_transform(X) |
|
|
|
|
|
self.model.fit(X_scaled, y) |
|
self.is_trained = True |
|
|
|
|
|
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 |
|
|
|
|
|
X = np.array([setup_params]).reshape(1, -1) |
|
X_scaled = self.scaler.transform(X) |
|
|
|
|
|
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) |
|
|
|
|
|
bounds = [ |
|
(5, 25), |
|
(8, 35), |
|
(20, 80), |
|
(50, 150), |
|
(600, 1200), |
|
(0.5, 2.0) |
|
] |
|
|
|
|
|
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)) |
|
|
|
|
|
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) |
|
|
|
|
|
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) |
|
|
|
|
|
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) |
|
|
|
|
|
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)) |
|
|
|
|
|
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) |
|
|
|
|
|
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) |
|
|
|
|
|
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) |
|
|
|
|
|
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 |
|
|
|
|
|
predictor = F1AerodynamicPredictor() |
|
|
|
def analyze_aerodynamics(): |
|
"""Main aerodynamic analysis function""" |
|
|
|
data = predictor.generate_aero_data(2000) |
|
|
|
|
|
r2, rmse = predictor.train_model(data) |
|
|
|
|
|
fig = predictor.create_visualizations(data) |
|
|
|
|
|
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 |
|
|
|
|
|
user_data, message = predictor.load_user_data(file) |
|
if user_data is None: |
|
return None, message, None |
|
|
|
|
|
r2, rmse = predictor.train_model(user_data) |
|
|
|
|
|
fig = predictor.create_visualizations(user_data) |
|
|
|
|
|
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." |
|
|
|
|
|
synthetic_data = predictor.generate_aero_data(len(predictor.current_data)) |
|
|
|
|
|
fig = predictor.compare_datasets(synthetic_data, predictor.current_data) |
|
|
|
|
|
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) |
|
|
|
|
|
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") |
|
|
|
|
|
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") |
|
|
|
|
|
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() |