tracinginsights's picture
download
raw
22.1 kB
import json
import os
import fastf1
import numpy as np
import pandas as pd
import utils
fastf1.Cache.enable_cache("cache")
YEAR = 2025
def events_available(year: int) -> any:
# get events available for a given year
data = utils.LatestData(year)
events = data.get_events()
return events
events = [
# 'Australian Grand Prix',
# 'Chinese Grand Prix',
# 'Japanese Grand Prix',
# 'Bahrain Grand Prix',
# 'Saudi Arabian Grand Prix',
# 'Miami Grand Prix',
# "Emilia Romagna Grand Prix",
# 'Monaco Grand Prix',
# 'Spanish Grand Prix',
# 'Canadian Grand Prix',
# 'Austrian Grand Prix',
# 'British Grand Prix',
# 'Belgian Grand Prix',
# 'Hungarian Grand Prix',
# 'Dutch Grand Prix',
# 'Italian Grand Prix',
# 'Azerbaijan Grand Prix',
# 'Singapore Grand Prix',
# 'United States Grand Prix',
# 'Mexico City Grand Prix',
# 'São Paulo Grand Prix',
# 'Las Vegas Grand Prix',
# 'Qatar Grand Prix',
# 'Abu Dhabi Grand Prix',
]
sessions = [
# "Practice 1",
# "Practice 2",
"Practice 3",
# "Qualifying",
# "Race",
#"Sprint",
# "Sprint Qualifying",
]
def sessions_available(year: int, event: str | int) -> any:
# get sessions available for a given year and event
event = str(event)
data = utils.LatestData(year)
sessions = data.get_sessions(event)
return sessions
def get_sessions(year, event):
p1_p2_p3 = ["Practice 1", "Practice 2", "Practice 3"]
p1_p2_q_r = ["Practice 1", "Practice 2", "Qualifying", "Race"]
p2_p3_q_r = ["Practice 2", "Practice 3", "Qualifying", "Race"]
p3_q_r = ["Practice 3", "Qualifying", "Race"]
p1_q_r = ["Practice 1", "Qualifying", "Race"]
normal_sessions = [
"Practice 1",
"Practice 2",
"Practice 3",
"Qualifying",
"Race",
]
normal_sprint = [
"Practice 1",
"Qualifying",
"Practice 2",
"Sprint Qualifying",
"Race",
]
sprint_2022 = [
"Practice 1",
"Qualifying",
"Practice 2",
"Sprint",
"Race",
]
sprint_shootout = [
"Practice 1",
"Qualifying",
"Sprint Shootout",
"Sprint",
"Race",
]
sprint_shootout_2024 = [
"Practice 1",
"Sprint Shootout",
"Sprint",
"Qualifying",
"Race",
]
if year == 2018:
return normal_sessions
if year == 2019:
if event == "Japanese Grand Prix":
return p1_p2_q_r
return normal_sessions
if year == 2020:
if event == "Styrian Grand Prix":
return p1_p2_q_r
if event == "Eifel Grand Prix":
return p3_q_r
if event == "Emilia Romagna Grand Prix":
return p1_q_r
return normal_sessions
if year == 2021:
if (
event == "British Grand Prix"
or event == "Italian Grand Prix"
or event == "São Paulo Grand Prix"
):
return normal_sprint
else:
return normal_sessions
if year == 2022:
if event == "Pre-Season Test":
return p1_p2_p3
if (
event == "Austrian Grand Prix"
or event == "Emilia Romagna Grand Prix"
or event == "São Paulo Grand Prix"
):
return sprint_2022
else:
return normal_sessions
if year == 2023:
if event == "Pre-Season Testing":
return p1_p2_p3
if event == "Hungarian Grand Prix":
return p2_p3_q_r
if (
event == "Austrian Grand Prix"
or event == "Azerbaijan Grand Prix"
or event == "Belgium Grand Prix"
or event == "Qatar Grand Prix"
or event == "United States Grand Prix"
or event == "São Paulo Grand Prix"
):
return sprint_shootout
else:
return normal_sessions
if year == 2024:
if event == "Pre-Season Testing":
return p1_p2_p3
if (
event == "Chinese Grand Prix"
or event == "Miami Grand Prix"
or event == "Austrian Grand Prix"
or event == "United States Grand Prix"
or event == "São Paulo Grand Prix"
or event == "Qatar Grand Prix"
):
return sprint_shootout_2024
return normal_sessions
def session_drivers(year: int, event: str | int, session: str) -> any:
# get drivers available for a given year, event and session
import fastf1
f1session = fastf1.get_session(year, event, session)
f1session.load(telemetry=True, weather=False, messages=False)
laps = f1session.laps
team_colors = utils.team_colors(year)
# add team_colors dict to laps on Team column
laps["color"] = laps["Team"].map(team_colors)
unique_drivers = laps["Driver"].unique()
drivers = [
{
"driver": driver,
"team": laps[laps.Driver == driver].Team.iloc[0],
}
for driver in unique_drivers
]
return {"drivers": drivers}
def session_drivers_list(year: int, event: str | int, session: str) -> any:
# get drivers available for a given year, event and session
import fastf1
f1session = fastf1.get_session(year, event, session)
f1session.load(telemetry=True, weather=False, messages=False)
laps = f1session.laps
unique_drivers = laps["Driver"].unique()
return list(unique_drivers)
def laps_data(year: int, event: str | int, session: str, driver: str) -> any:
# get drivers available for a given year, event, and session
f1session = fastf1.get_session(year, event, session)
f1session.load(telemetry=False, weather=False, messages=False)
laps = f1session.laps
# add team_colors dict to laps on Team column
# for each driver in drivers, get the Team column from laps and get the color from team_colors dict
drivers_data = []
driver_laps = laps.pick_driver(driver)
driver_laps["LapTime"] = driver_laps["LapTime"].dt.total_seconds()
# remove rows where LapTime is null
driver_laps = driver_laps[driver_laps.LapTime.notnull()]
drivers_data = {
"time": driver_laps["LapTime"].tolist(),
"lap": driver_laps["LapNumber"].tolist(),
"compound": driver_laps["Compound"].tolist(),
}
return drivers_data
# # Example usage:
# result = laps_data(2018, "Bahrain", "R", "GAS")
# result
def accCalc(allLapsDriverTelemetry, Nax, Nay, Naz):
vx = allLapsDriverTelemetry["Speed"] / 3.6
time_float = allLapsDriverTelemetry["Time"] / np.timedelta64(1, "s")
dtime = np.gradient(time_float)
ax = np.gradient(vx) / dtime
for i in np.arange(1, len(ax) - 1).astype(int):
if ax[i] > 25:
ax[i] = ax[i - 1]
ax_smooth = np.convolve(ax, np.ones((Nax,)) / Nax, mode="same")
x = allLapsDriverTelemetry["X"]
y = allLapsDriverTelemetry["Y"]
z = allLapsDriverTelemetry["Z"]
dx = np.gradient(x)
dy = np.gradient(y)
dz = np.gradient(z)
theta = np.arctan2(dy, (dx + np.finfo(float).eps))
theta[0] = theta[1]
theta_noDiscont = np.unwrap(theta)
dist = allLapsDriverTelemetry["Distance"]
ds = np.gradient(dist)
dtheta = np.gradient(theta_noDiscont)
for i in np.arange(1, len(dtheta) - 1).astype(int):
if abs(dtheta[i]) > 0.5:
dtheta[i] = dtheta[i - 1]
C = dtheta / (ds + 0.0001) # To avoid division by 0
ay = np.square(vx) * C
indexProblems = np.abs(ay) > 150
ay[indexProblems] = 0
ay_smooth = np.convolve(ay, np.ones((Nay,)) / Nay, mode="same")
# for z
z_theta = np.arctan2(dz, (dx + np.finfo(float).eps))
z_theta[0] = z_theta[1]
z_theta_noDiscont = np.unwrap(z_theta)
dist = allLapsDriverTelemetry["Distance"]
ds = np.gradient(dist)
z_dtheta = np.gradient(z_theta_noDiscont)
for i in np.arange(1, len(z_dtheta) - 1).astype(int):
if abs(z_dtheta[i]) > 0.5:
z_dtheta[i] = z_dtheta[i - 1]
z_C = z_dtheta / (ds + 0.0001) # To avoid division by 0
az = np.square(vx) * z_C
indexProblems = np.abs(az) > 150
az[indexProblems] = 0
az_smooth = np.convolve(az, np.ones((Naz,)) / Naz, mode="same")
allLapsDriverTelemetry["Ax"] = ax_smooth
allLapsDriverTelemetry["Ay"] = ay_smooth
allLapsDriverTelemetry["Az"] = az_smooth
return allLapsDriverTelemetry
def telemetry_data(year, event, session: str, driver, lap_number):
f1session = fastf1.get_session(year, event, session)
f1session.load(telemetry=True, weather=False, messages=False)
laps = f1session.laps
driver_laps = laps.pick_driver(driver)
driver_laps["LapTime"] = driver_laps["LapTime"].dt.total_seconds()
# get the telemetry for lap_number
selected_lap = driver_laps[driver_laps.LapNumber == lap_number]
telemetry = selected_lap.get_telemetry()
acc_tel = accCalc(telemetry, 3, 9, 9)
acc_tel["Time"] = acc_tel["Time"].dt.total_seconds()
laptime = selected_lap.LapTime.values[0]
# data_key = f"{driver} - Lap {int(lap_number)} - {year} - {session} - [{laptime}]"
data_key = f"{year}-{event}-{session}-{driver}-{lap_number}"
acc_tel["DRS"] = acc_tel["DRS"].apply(lambda x: 1 if x in [10, 12, 14] else 0)
acc_tel["Brake"] = acc_tel["Brake"].apply(lambda x: 1 if x == True else 0)
telemetry_data = {
"tel": {
"time": acc_tel["Time"].tolist(),
"rpm": acc_tel["RPM"].tolist(),
"speed": acc_tel["Speed"].tolist(),
"gear": acc_tel["nGear"].tolist(),
"throttle": acc_tel["Throttle"].tolist(),
"brake": acc_tel["Brake"].tolist(),
"drs": acc_tel["DRS"].tolist(),
"distance": acc_tel["Distance"].tolist(),
"rel_distance": acc_tel["RelativeDistance"].tolist(),
"acc_x": acc_tel["Ax"].tolist(),
"acc_y": acc_tel["Ay"].tolist(),
"acc_z": acc_tel["Az"].tolist(),
"x": acc_tel["X"].tolist(),
"y": acc_tel["Y"].tolist(),
"z": acc_tel["Z"].tolist(),
"dataKey": data_key,
}
}
return telemetry_data
while True:
try:
# Your list of events
events_list = events
# Loop through each event
for event in events_list:
# Get sessions for the current event
# sessions = sessions_available(YEAR, event)
# Loop through each session and create a folder within the event folder
for session in sessions:
drivers = session_drivers_list(YEAR, event, session)
for driver in drivers:
f1session = fastf1.get_session(YEAR, event, session)
f1session.load(telemetry=False, weather=False, messages=False)
laps = f1session.laps
driver_laps = laps.pick_driver(driver)
driver_laps["LapNumber"] = driver_laps["LapNumber"].astype(int)
driver_lap_numbers = round(driver_laps["LapNumber"]).tolist()
for lap_number in driver_lap_numbers:
driver_folder = f"{event}/{session}/{driver}"
if not os.path.exists(driver_folder):
os.makedirs(driver_folder)
try:
telemetry = telemetry_data(YEAR, event, session, driver, lap_number)
# print(telemetry)
# Specify the file path where you want to save the JSON data
file_path = f"{driver_folder}/{lap_number}_tel.json"
# Save the dictionary to a JSON file
with open(file_path, "w") as json_file:
json.dump(telemetry, json_file)
except:
continue
def session_drivers(year: int, event: str | int, session: str) -> any:
# get drivers available for a given year, event and session
import fastf1
f1session = fastf1.get_session(year, event, session)
f1session.load(telemetry=True, weather=False, messages=False)
laps = f1session.laps
team_colors = utils.team_colors(year)
# add team_colors dict to laps on Team column
laps["color"] = laps["Team"].map(team_colors)
unique_drivers = laps["Driver"].unique()
drivers = [
{
"driver": driver,
"team": laps[laps.Driver == driver].Team.iloc[0],
}
for driver in unique_drivers
]
return {"drivers": drivers}
import json
import os
import utils
# Loop through each event
for event in events_list:
# sessions = sessions_available(YEAR, event)
# sessions = ['Practice 1','Practice 2','Practice 3']
# Loop through each session and create a folder within the event folder
for session in sessions:
drivers = session_drivers(YEAR, event, session)
import json
# Specify the file path where you want to save the JSON data
file_path = f"{event}/{session}/drivers.json"
# Save the dictionary to a JSON file
with open(file_path, "w") as json_file:
json.dump(drivers, json_file)
print(f"Dictionary saved to {file_path}")
def session_drivers_list(year: int, event: str | int, session: str) -> any:
# get drivers available for a given year, event and session
import fastf1
f1session = fastf1.get_session(year, event, session)
f1session.load(telemetry=True, weather=False, messages=False)
laps = f1session.laps
unique_drivers = laps["Driver"].unique()
return list(unique_drivers)
def laps_data(year: int, event: str | int, session: str, driver: str) -> any:
# get drivers available for a given year, event, and session
f1session = fastf1.get_session(year, event, session)
f1session.load(telemetry=False, weather=False, messages=False)
laps = f1session.laps
# add team_colors dict to laps on Team column
# for each driver in drivers, get the Team column from laps and get the color from team_colors dict
drivers_data = []
driver_laps = laps.pick_driver(driver)
driver_laps["LapTime"] = driver_laps["LapTime"].dt.total_seconds()
# remove rows where LapTime is null
driver_laps = driver_laps[driver_laps.LapTime.notnull()]
drivers_data = {
"time": driver_laps["LapTime"].tolist(),
"lap": driver_laps["LapNumber"].tolist(),
"compound": driver_laps["Compound"].tolist(),
}
return drivers_data
# Loop through each event
for event in events_list:
# # Get sessions for the current event
# if event == "Qatar Grand Prix":
# sessions = ['Practice 1', 'Qualifying', 'Sprint Shootout', 'Sprint', 'Race']
# else:
# sessions = sessions_available(YEAR, event)
# Loop through each session and create a folder within the event folder
for session in sessions:
drivers = session_drivers_list(YEAR, event, session)
for driver in drivers:
# Create a folder for the driver if it doesn't exist
driver_folder = f"{event}/{session}/{driver}"
if not os.path.exists(driver_folder):
os.makedirs(driver_folder)
laptimes = laps_data(YEAR, event, session, driver)
# Specify the file path where you want to save the JSON data
file_path = f"{driver_folder}/laptimes.json"
# Save the dictionary to a JSON file
with open(file_path, "w") as json_file:
json.dump(laptimes, json_file)
# print(f"Dictionary saved to {file_path}")
# corners
import fastf1
import os
import json
import utils
def sessions_available(year: int, event: str | int) -> any:
# get sessions available for a given year and event
event = str(event)
data = utils.LatestData(year)
sessions = data.get_sessions(event)
return sessions
for event in events:
for session in sessions:
f1session = fastf1.get_session(YEAR, event, session)
f1session.load()
circuit_info = f1session.get_circuit_info().corners
corner_info ={
"CornerNumber": circuit_info['Number'].tolist(),
"X": circuit_info['X'].tolist(),
"Y": circuit_info['Y'].tolist(),
"Angle": circuit_info['Angle'].tolist(),
"Distance": circuit_info['Distance'].tolist(),
}
driver_folder = f"{event}/{session}"
file_path = f"{event}/{session}/corners.json"
if not os.path.exists(driver_folder):
os.makedirs(driver_folder)
# Save the dictionary to a JSON file
with open(file_path, "w") as json_file:
json.dump(corner_info, json_file)
break
except:
import time
time.sleep(5)
continue
# corner data
from fastf1.req import Cache
PROTO = "https"
HOST = "api.multiviewer.app"
HEADERS = {'User-Agent': f'FastF1/'}
def _make_url(path: str):
return f"{PROTO}://{HOST}{path}"
def get_circuit(*, year: int, circuit_key: int) :
""":meta private:
Request circuit data from the MultiViewer API and return the JSON
response."""
url = _make_url(f"/api/v1/circuits/{circuit_key}/{year}")
response = Cache.requests_get(url, headers=HEADERS)
if response.status_code != 200:
_logger.debug(f"[{response.status_code}] {response.content.decode()}")
return None
try:
return response.json()
except requests.exceptions.JSONDecodeError:
return None
def get_circuit_info(*, year: int, circuit_key: int):
""":meta private:
Load circuit information from the MultiViewer API and convert it into
as :class:``SessionInfo`` object.
Args:
year: The championship year
circuit_key: The unique circuit key (defined by the F1 livetiming API)
"""
data = get_circuit(year=year, circuit_key=circuit_key)
if not data:
_logger.warning("Failed to load circuit info")
return None
ret = list()
for cat in ('corners', 'marshalLights', 'marshalSectors'):
rows = list()
for entry in data[cat]:
rows.append((
float(entry.get('trackPosition', {}).get('x', 0.0)),
float(entry.get('trackPosition', {}).get('y', 0.0)),
int(entry.get('number', 0)),
str(entry.get('letter', "")),
float(entry.get('angle', 0.0)),
float(entry.get('length',0.0))
))
ret.append(
pd.DataFrame(
rows,
columns=['X', 'Y', 'Number', 'Letter', 'Angle', 'Distance']
)
)
rotation = float(data.get('rotation', 0.0))
circuit_info = ret[0]
return circuit_info
for event in events:
for session in sessions:
f1session = fastf1.get_session(YEAR, event, session)
f1session.load()
circuit_key = f1session.session_info['Meeting']['Circuit']['Key']
circuit_info = get_circuit_info(year=YEAR,
circuit_key=circuit_key)
corner_info ={
"CornerNumber": circuit_info['Number'].tolist(),
"X": circuit_info['X'].tolist(),
"Y": circuit_info['Y'].tolist(),
"Angle": circuit_info['Angle'].tolist(),
"Distance": (circuit_info['Distance']/10).tolist(),
}
driver_folder = f"{event}/{session}"
file_path = f"{event}/{session}/corners.json"
if not os.path.exists(driver_folder):
os.makedirs(driver_folder)
# Save the dictionary to a JSON file
with open(file_path, "w") as json_file:
json.dump(corner_info, json_file)

Xet Storage Details

Size:
22.1 kB
·
Xet hash:
35501a5523735339b66e83bedf47e3a8822831f9245697e63995cba2e661498b

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.