arre99 commited on
Commit
18c04d1
·
1 Parent(s): 95e43e2

fix conversion for round parameter so it is converted to integer if isnumeric is true. Added some extra comments to make it more clear to the user how to interact with the Gradio UI

Browse files
Files changed (3) hide show
  1. app.py +22 -17
  2. fastf1_tools.py +15 -3
  3. todo.txt +1 -3
app.py CHANGED
@@ -1,4 +1,5 @@
1
  import gradio as gr
 
2
 
3
  # Local modules
4
  import fastf1_tools
@@ -17,8 +18,8 @@ iface_driver_championship_standings = gr.Interface(
17
  gr.Dropdown(label="Driver", choices=DRIVER_NAMES)
18
  ],
19
  outputs="text",
20
- title="Driver Championship Standings",
21
- description="Get the driver championship standings"
22
  )
23
 
24
  iface_constructor_championship_standings = gr.Interface(
@@ -28,20 +29,20 @@ iface_constructor_championship_standings = gr.Interface(
28
  gr.Dropdown(label="Constructor", choices=CONSTRUCTOR_NAMES)
29
  ],
30
  outputs="text",
31
- title="Constructor Championship Standings",
32
- description="Get the constructor championship standings"
33
  )
34
 
35
  iface_event_info = gr.Interface(
36
  fn=fastf1_tools.get_event_info,
37
  inputs=[
38
  gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
39
- gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported)"),
40
  gr.Radio(["human", "LLM"], label="Display format", value="human")
41
  ],
42
  outputs="text",
43
  title="Event Info",
44
- description="Get the Grand Prix event info for a specific race week"
45
  )
46
 
47
  iface_season_calendar = gr.Interface(
@@ -51,32 +52,36 @@ iface_season_calendar = gr.Interface(
51
  ],
52
  outputs="text",
53
  title="Season Calendar",
54
- description="Get the season calendar information for the given year"
55
  )
56
 
57
  iface_track_visualization = gr.Interface(
58
  fn=fastf1_tools.track_visualization,
59
  inputs=[
60
  gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
61
- gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported)"),
62
- gr.Radio(["speed", "corners", "gear"], label="Visualization type", value="speed"),
63
- gr.Dropdown(DRIVER_NAMES)
64
  ],
65
  outputs="image",
66
  title="Track Visualizations",
67
- description="Get the track visualization for the given Grand Prix"
68
  )
69
 
70
  iface_session_results = gr.Interface(
71
  fn=fastf1_tools.get_session_results,
72
  inputs=[
73
  gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
74
- gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported)"),
75
- gr.Dropdown([session_type for session_type in DROPDOWN_SESSION_TYPES if "practice" not in session_type], label="Session type", value="race")
76
  ],
77
- outputs=gr.DataFrame(),
 
 
 
 
78
  title="Session Results",
79
- description="Get the session results for the given Grand Prix"
80
  )
81
 
82
  iface_driver_info = gr.Interface(
@@ -86,7 +91,7 @@ iface_driver_info = gr.Interface(
86
  ],
87
  outputs="text",
88
  title="Driver Info",
89
- description="Get information about a specific driver"
90
  )
91
 
92
  iface_constructor_info = gr.Interface(
@@ -96,7 +101,7 @@ iface_constructor_info = gr.Interface(
96
  ],
97
  outputs="text",
98
  title="Constructor Info",
99
- description="Get information about a specific constructor"
100
  )
101
 
102
 
 
1
  import gradio as gr
2
+ import pandas as pd
3
 
4
  # Local modules
5
  import fastf1_tools
 
18
  gr.Dropdown(label="Driver", choices=DRIVER_NAMES)
19
  ],
20
  outputs="text",
21
+ title="World Driver Championship Standings",
22
+ description="Get the world driver championship standings for a specific driver"
23
  )
24
 
25
  iface_constructor_championship_standings = gr.Interface(
 
29
  gr.Dropdown(label="Constructor", choices=CONSTRUCTOR_NAMES)
30
  ],
31
  outputs="text",
32
+ title="World Constructor Championship Standings",
33
+ description="Get the world constructor championship standings for a specific constructor"
34
  )
35
 
36
  iface_event_info = gr.Interface(
37
  fn=fastf1_tools.get_event_info,
38
  inputs=[
39
  gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
40
+ gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported) or round number"),
41
  gr.Radio(["human", "LLM"], label="Display format", value="human")
42
  ],
43
  outputs="text",
44
  title="Event Info",
45
+ description="Get information about a specific Grand Prix event. Example: (2025,Monaco,human)"
46
  )
47
 
48
  iface_season_calendar = gr.Interface(
 
52
  ],
53
  outputs="text",
54
  title="Season Calendar",
55
+ description="Get the season calendar for the given year"
56
  )
57
 
58
  iface_track_visualization = gr.Interface(
59
  fn=fastf1_tools.track_visualization,
60
  inputs=[
61
  gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
62
+ gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported) or round number"),
63
+ gr.Radio(["speed", "corners", "gear"], label="Visualization type", value="speed", info="What type of track visualization to generate"),
64
+ gr.Dropdown(label="Driver", choices=DRIVER_NAMES, info="Only applied for speed visualization. gear uses fastest lap during race.")
65
  ],
66
  outputs="image",
67
  title="Track Visualizations",
68
+ description="Get the track visualization for the given Grand Prix. Example: (2025,Monaco,speed,Leclerc)"
69
  )
70
 
71
  iface_session_results = gr.Interface(
72
  fn=fastf1_tools.get_session_results,
73
  inputs=[
74
  gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
75
+ gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported) or round number"),
76
+ gr.Dropdown([session_type for session_type in DROPDOWN_SESSION_TYPES if "practice" not in session_type], label="Session type", value="race", info="The session type to get results for. Dataframe's columns vary depending on session type.")
77
  ],
78
+ outputs=gr.Dataframe(
79
+ headers=None, # Let it infer from returned DataFrame
80
+ row_count=(0, "dynamic"), # Start empty, allow it to grow
81
+ col_count=(0, "dynamic") # Let columns adjust too
82
+ ),
83
  title="Session Results",
84
+ description="Get the session results for the given Grand Prix. Example: (2025,Monaco,qualifying)"
85
  )
86
 
87
  iface_driver_info = gr.Interface(
 
91
  ],
92
  outputs="text",
93
  title="Driver Info",
94
+ description="Get background information about a specific driver"
95
  )
96
 
97
  iface_constructor_info = gr.Interface(
 
101
  ],
102
  outputs="text",
103
  title="Constructor Info",
104
+ description="Get background information about a specific constructor"
105
  )
106
 
107
 
fastf1_tools.py CHANGED
@@ -48,6 +48,9 @@ def get_session(year: int, round: gp, session_type: session_type) -> Session:
48
  if isinstance(session_type, str):
49
  if session_type.lower() not in AVAILABLE_SESSION_TYPES:
50
  return f"Session type {session_type} is not available. Supported session types: {AVAILABLE_SESSION_TYPES}"
 
 
 
51
 
52
  return fastf1.get_session(year, round, session_type)
53
 
@@ -75,6 +78,9 @@ def get_event_info(year: int, round: gp, format: str) -> str:
75
  str: Formatted event information based on the specified format
76
  """
77
 
 
 
 
78
  event = fastf1.get_session(year, round, "race").event # Event object is the same for all sessions, so hardcode "race"
79
  if format == "human":
80
  data_interval = f"{event['Session1DateUtc'].date()} - {event['Session5DateUtc'].date()}"
@@ -173,6 +179,8 @@ def track_visualization(year: int, round: gp, visualization_type: str, driver_na
173
  Returns:
174
  Image.Image: A PIL Image object containing the visualization
175
  """
 
 
176
 
177
  session = get_session(year, round, "race")
178
  session.load()
@@ -196,17 +204,21 @@ def get_session_results(year: int, round: gp, session_type: session_type) -> pd.
196
  pd.DataFrame: DataFrame containing the session results
197
 
198
  Raises:
199
- gr.Error: If the session type is not supported for the specified round
200
  """
 
 
201
 
202
  try:
203
  session = get_session(year, round, session_type)
204
  session.load(telemetry=False)
205
- results = session.results
 
 
206
  except ValueError as e:
207
  raise gr.Error(f"Session type {session_type} is not supported for the specified round. This Grand Prix most likely did not include a sprint race/quali.")
208
 
209
- df = results[["DriverNumber", "Abbreviation", "FullName", "Position", "GridPosition", "Points", "Status", "Q1", "Q2", "Q3"]]
210
  df["Name"] = df.apply(lambda row: f"{row['FullName']} ({row['Abbreviation']} • {row['DriverNumber']})", axis=1)
211
  df = df.drop(columns=["FullName", "Abbreviation", "DriverNumber"])
212
  df = df.rename(columns={"Position": "Pos", "GridPosition": "Grid Pos"})
 
48
  if isinstance(session_type, str):
49
  if session_type.lower() not in AVAILABLE_SESSION_TYPES:
50
  return f"Session type {session_type} is not available. Supported session types: {AVAILABLE_SESSION_TYPES}"
51
+
52
+ if isinstance(round, str) and round.isnumeric():
53
+ round = int(round)
54
 
55
  return fastf1.get_session(year, round, session_type)
56
 
 
78
  str: Formatted event information based on the specified format
79
  """
80
 
81
+ if isinstance(round, str) and round.isnumeric():
82
+ round = int(round)
83
+
84
  event = fastf1.get_session(year, round, "race").event # Event object is the same for all sessions, so hardcode "race"
85
  if format == "human":
86
  data_interval = f"{event['Session1DateUtc'].date()} - {event['Session5DateUtc'].date()}"
 
179
  Returns:
180
  Image.Image: A PIL Image object containing the visualization
181
  """
182
+ if isinstance(round, str) and round.isnumeric():
183
+ round = int(round)
184
 
185
  session = get_session(year, round, "race")
186
  session.load()
 
204
  pd.DataFrame: DataFrame containing the session results
205
 
206
  Raises:
207
+ ValueError: If the session type is invalid
208
  """
209
+ if isinstance(round, str) and round.isnumeric():
210
+ round = int(round)
211
 
212
  try:
213
  session = get_session(year, round, session_type)
214
  session.load(telemetry=False)
215
+ # Create a proper copy of the results DataFrame
216
+ df = session.results[['DriverNumber', 'Abbreviation', 'FullName', 'Position',
217
+ 'GridPosition', 'Points', 'Status', 'Q1', 'Q2', 'Q3']].copy()
218
  except ValueError as e:
219
  raise gr.Error(f"Session type {session_type} is not supported for the specified round. This Grand Prix most likely did not include a sprint race/quali.")
220
 
221
+ # Now we can safely modify the DataFrame
222
  df["Name"] = df.apply(lambda row: f"{row['FullName']} ({row['Abbreviation']} • {row['DriverNumber']})", axis=1)
223
  df = df.drop(columns=["FullName", "Abbreviation", "DriverNumber"])
224
  df = df.rename(columns={"Position": "Pos", "GridPosition": "Grid Pos"})
todo.txt CHANGED
@@ -2,6 +2,4 @@
2
  * Solution is to have a static json file that maps drivers for each season/year
3
  - Same applies for constructor championship standings but instead Constructor dropdown
4
  * Similar solution to above
5
- - Implement a tab for the OpenF1 tools but it might not be that user friendly :/
6
- - Add some helpful info for each Gradio Tab to help user understand what they are able to do
7
- - for session result remove the default placeholder value
 
2
  * Solution is to have a static json file that maps drivers for each season/year
3
  - Same applies for constructor championship standings but instead Constructor dropdown
4
  * Similar solution to above
5
+ - Implement a tab for the OpenF1 tools but it might not be that user friendly :/