### Install LiveF1 from Source Source: http://livef1.goktugocal.com/_sources/getting_started/installation.rst.txt Install dependencies and the LiveF1 package after cloning the repository. This is for development or contributing. ```bash pip install -r requirements.txt pip install . ``` -------------------------------- ### Complete Real-Time Client Example Source: http://livef1.goktugocal.com/user_guide/realtime_data.html A comprehensive example demonstrating client initialization with multiple topics, defining distinct handlers for telemetry and track status, and running the client. ```python from livef1.adapters.realtime_client import RealF1Client import datetime import json # Initialize client client = RealF1Client( topics=["CarData.z", "SessionInfo", "TrackStatus"], log_file_name="session_data.json" ) # Define multiple handlers @client.callback("process_telemetry") async def handle_telemetry(records): # Process car telemetry data telemetry_data = records.get("CarData.z") if telemetry_data: for record in telemetry_data: process_telemetry_data(record) # this is a placeholder for your code @client.callback("track_status") async def handle_track_status(records): # Monitor track conditions track_data = records.get("TrackStatus") if track_data: for record in track_data: update_track_status(record) # this is a placeholder for your code # Start the client client.run() ``` -------------------------------- ### Example Session Data Output Source: http://livef1.goktugocal.com/_sources/getting_started/quick_start.rst.txt This is an example output showing the available data topics for a session, including Session_Info, Track_Status, and Car_Data. ```none | | Season Year | Meeting Location | Session Type | Meeting Code | Meeting Key | Meeting Number | Meeting Offname | Meeting Name | Meeting Country Key | Meeting Country Code | Meeting Country Name | Meeting Circuit Key | Meeting Circuit Shortname | Session Key | Session Name | Session Startdate | Session Enddate | Gmtoffset | Path | |---:|--------------:|:-------------------|:---------------|:---------------|--------------:|-----------------:|:----------------------------------------|:-------------------|----------------------:|:-----------------------|:-----------------------|----------------------:|:----------------------------|--------------:|:---------------|:--------------------|:--------------------|:------------|:----------------------------------------------------------| | 0 | 2024 | Spa-Francorchamps | Practice 1 | BEL02012 | 1242 | 14 | FORMULA 1 ROLEX BELGIAN GRAND PRIX 2024 | Belgian Grand Prix | 16 | BEL | Belgium | 7 | Spa-Francorchamps | 9567 | Practice 1 | 2024-07-26 13:30:00 | 2024-07-26 14:30:00 | 02:00:00 | 2024/2024-07-28_Belgian_Grand_Prix/2024-07-26_Practice_1/ | | 1 | 2024 | Spa-Francorchamps | Practice 2 | BEL02012 | 1242 | 14 | FORMULA 1 ROLEX BELGIAN GRAND PRIX 2024 | Belgian Grand Prix | 16 | BEL | Belgium | 7 | Spa-Francorchamps | 9568 | Practice 2 | 2024-07-26 17:00:00 | 2024-07-26 18:00:00 | 02:00:00 | 2024/2024-07-28_Belgian_Grand_Prix/2024-07-26_Practice_2/ | | 2 | 2024 | Spa-Francorchamps | Practice 3 | BEL02012 | 1242 | 14 | FORMULA 1 ROLEX BELGIAN GRAND PRIX 2024 | Belgian Grand Prix | 16 | BEL | Belgium | 7 | Spa-Francorchamps | 9569 | Practice 3 | 2024-07-27 12:30:00 | 2024-07-27 13:30:00 | 02:00:00 | 2024/2024-07-28_Belgian_Grand_Prix/2024-07-27_Practice_3/ | | 3 | 2024 | Spa-Francorchamps | Qualifying | BEL02012 | 1242 | 14 | FORMULA 1 ROLEX BELGIAN GRAND PRIX 2024 | Belgian Grand Prix | 16 | BEL | Belgium | 7 | Spa-Francorchamps | 9570 | Qualifying | 2024-07-27 16:00:00 | 2024-07-27 17:00:00 | 02:00:00 | 2024/2024-07-28_Belgian_Grand_Prix/2024-07-27_Qualifying/ | | 4 | 2024 | Spa-Francorchamps | Race | BEL02012 | 1242 | 14 | FORMULA 1 ROLEX BELGIAN GRAND PRIX 2024 | Belgian Grand Prix | 16 | BEL | Belgium | 7 | Spa-Francorchamps | 9574 | Race | 2024-07-28 15:00:00 | 2024-07-28 17:00:00 | 02:00:00 | 2024/2024-07-28_Belgian_Grand_Prix/2024-07-28_Race/ | ``` ```none Session_Info : Details about the current session. Archive_Status : Status of archived session data. Track_Status : Current conditions and status of the track. Session_Data : Raw data for the ongoing session. Position : Position data of cars. Car_Data : Car sensor data. . . . ``` -------------------------------- ### Complete Real-Time Client Example Source: http://livef1.goktugocal.com/_sources/user_guide/realtime_data.rst.txt A comprehensive example demonstrating client initialization with multiple topics and a log file, along with defining and registering two distinct asynchronous handlers for telemetry and track status data. ```python from livef1.adapters.realtime_client import RealF1Client import datetime import json # Initialize client client = RealF1Client( topics=["CarData.z", "SessionInfo", "TrackStatus"], log_file_name="session_data.json" ) # Define multiple handlers @client.callback("process_telemetry") async def handle_telemetry(records): # Process car telemetry data telemetry_data = records.get("CarData.z") if telemetry_data: for record in telemetry_data: process_telemetry_data(record) # this is a placeholder for your code @client.callback("track_status") async def handle_track_status(records): # Monitor track conditions track_data = records.get("TrackStatus") if track_data: for record in track_data: update_track_status(record) # this is a placeholder for your code # Start the client client.run() ``` -------------------------------- ### Example Usage with RealF1Client Source: http://livef1.goktugocal.com/_sources/user_guide/logging_config.rst.txt Demonstrates integrating logging within a RealF1Client callback. This example enables debug logging and logs messages during data processing. ```python from livef1.adapters.realtime_client import RealF1Client from livef1.utils.logger import logger, set_log_level import logging # Enable debug logging set_log_level('DEBUG') # Initialize client client = RealF1Client(topics=["CarData.z"]) @client.callback("logging_example") async def handle_data(records): logger.debug(f"Received {len(records)} records") logger.info("Processing new data batch") try: # Process records process_records(records) except Exception as e: logger.error(f"Error processing records: {e}") ``` -------------------------------- ### Install LiveF1 via Pip Source: http://livef1.goktugocal.com/_sources/getting_started/installation.rst.txt Use this command to install the LiveF1 library using pip. This is the recommended method for most users. ```bash pip install livef1 ``` -------------------------------- ### Load Start Coordinates Source: http://livef1.goktugocal.com/_modules/livef1/models/circuit.html Loads the start coordinates and direction for a circuit from an external API. This method should be called to populate circuit start data. ```python def _load_start_coordinates(self): """ Load the start coordinates of the circuit from an external API. """ response = requests.get(START_COORDINATES_URL) if response.status_code == 200: data = response.json() try: self.start_coordinates = data[self.short_name]["start_coordinates"] self.start_direction = data[self.short_name]["start_direction"] except: pass else: raise Exception(f"Failed to load start coordinates: {response.status_code}") ``` -------------------------------- ### RealF1Client.run() Source: http://livef1.goktugocal.com/_modules/livef1/adapters/realtime_client.html Starts the RealF1Client in asynchronous mode to begin receiving and processing data. ```APIDOC ## run() ### Description Start the client in asynchronous mode. ### Method ```python run() ``` ``` -------------------------------- ### Get Session Start Datetime - LiveF1 Source: http://livef1.goktugocal.com/_modules/livef1/models/session.html Retrieves the session start datetime by finding the first 'Started' status in the Session_Data table. ```python def _get_session_start_datetime(self): # return pd.to_timedelta(self.get_data(dataNames="SessionStatus").set_index("status").loc["Started"].timestamp[0]) sess_data = self.get_data("Session_Data") first_date = helper.to_datetime(sess_data[sess_data["SessionStatus"] == "Started"].Utc).tolist()[0] return first_date ``` -------------------------------- ### Import LiveF1 Library Source: http://livef1.goktugocal.com/_sources/getting_started/quick_start.rst.txt Start by importing the LiveF1 library to access its functionalities. ```python import livef1 as livef1 ``` -------------------------------- ### Run Real-Time Client Source: http://livef1.goktugocal.com/user_guide/realtime_data.html Start the RealF1Client to establish a connection, subscribe to topics, and begin receiving real-time data. This call is blocking. ```python client.run() # Starts the client and begins receiving data ``` -------------------------------- ### Run Real-Time Client Source: http://livef1.goktugocal.com/_sources/user_guide/realtime_data.rst.txt Start the RealF1Client to begin receiving and processing real-time data. This call initiates the connection and activates registered callbacks. ```python client.run() # Starts the client and begins receiving data ``` -------------------------------- ### Parse Team Records (Commented Out) Source: http://livef1.goktugocal.com/_modules/livef1/data_processing/parse_functions.html Example of how team data might be processed, currently commented out. It structures team information with session keys. ```python # teams = data["Teams"] # records_teams = [] # for team in teams.values(): # record = { # "session_key": sessionKey, # **team # } # records_teams.append(record) # return records_drivers#, records_teams ``` -------------------------------- ### Initialize Session and Get Topic Names Source: http://livef1.goktugocal.com/_sources/user_guide/data_objects.rst.txt Initializes a Session object and retrieves the names of available data topics. Requires valid Season and Meeting objects. ```python from livef1.models.session import Session # Initialize a session session = Session(season=season_2023, meeting=meeting, name="Practice 1") # Get topic names topic_names = session.get_topic_names() # Load data for a specific topic data = session.load_data(dataName="Car_Data") ``` -------------------------------- ### Import Libraries for Race Analysis Source: http://livef1.goktugocal.com/_sources/examples/pipelines/race_analysis.rst.txt Imports necessary libraries for data manipulation, plotting, and the liveF1 SDK. Ensure these are installed before running. ```python import livef1 import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from datetime import timedelta ``` -------------------------------- ### get Source: http://livef1.goktugocal.com/_modules/livef1/models/session.html Retrieve one or multiple data topics from cache or load them, with optional parallel processing. ```APIDOC ## get ### Description Retrieve one or multiple data topics from cache or load them, with optional parallel processing. ### Method ```python def get(self, dataNames, level = "bronze", parallel: bool = False, force: bool = False) ``` ### Parameters #### Path Parameters * **data_names** (Union[str, List[str]]) - Required - Single data topic name or list of data topic names to retrieve * **parallel** (bool) - Optional - Whether to use parallel processing when fetching multiple topics. Defaults to False. * **force** (bool) - Optional - Whether to force download data even if it exists in cache. Defaults to False. ### Returns Union[BasicResult, Dict[str, BasicResult]] If a single topic is requested, returns its BasicResult object. If multiple topics are requested, returns a dictionary mapping topic names to their BasicResult objects. ### Examples ```python # Get single topic telemetry = session.get_data("CarData.z") # Get multiple topics in parallel (default) data = session.get_data(["CarData.z", "Position.z", "SessionStatus"]) # Get multiple topics sequentially data = session.get_data(["CarData.z", "Position.z"], parallel=False) # Force download data even if cached data = session.get_data("CarData.z", force=True) ``` ### Notes - Automatically handles both single and multiple data requests - Checks cache (data lake) before loading new data unless force=True - Uses parallel processing for multiple topics when parallel=True - Returns same format as input: single result for str input, dict for list input ``` -------------------------------- ### Run RealF1Client Asynchronously Source: http://livef1.goktugocal.com/_modules/livef1/adapters/realtime_client.html Starts the RealF1Client in asynchronous mode. This method initiates the underlying asynchronous engine to process real-time data. ```python client.run() ``` -------------------------------- ### Get Circuit Keys Data Source: http://livef1.goktugocal.com/_modules/livef1/utils/helper.html Fetches circuit keys data from a specified URL. Raises an exception if the request fails. ```python def get_circuit_keys(): response = requests.get(CIRCUIT_KEYS_URL) if response.status_code == 200: return pd.read_csv(CIRCUIT_KEYS_URL) else: raise Exception(f"Failed to load circuit keys: {response.status_code}") ``` -------------------------------- ### Get Meeting by Key Source: http://livef1.goktugocal.com/getting_started/quick_start.html Retrieve a meeting object using its season and a unique meeting identifier string. The livef1 library must be imported. ```python import livef1 as livef1 meeting = livef1.get_meeting( season=2024, meeting_identifier="Spa" ) print(meeting) ``` -------------------------------- ### Get Session Topics Index Source: http://livef1.goktugocal.com/_sources/livetimingf1/f1_data.rst.txt Discover the available data topics and their respective keyframe and stream paths for a specific Formula 1 session. ```json { "Feeds": { "SessionInfo": { "KeyFramePath": "SessionInfo.json", "StreamPath": "SessionInfo.jsonStream" }, "TrackStatus": { "KeyFramePath": "TrackStatus.json", "StreamPath": "TrackStatus.jsonStream" }, // ...other data topics } } ``` -------------------------------- ### Fetch Timing Data (Python) Source: http://livef1.goktugocal.com/_sources/livetimingf1/data_topics.rst.txt Use Python's requests library to get and parse the TimingDataF1.json file. This provides real-time timing data for each driver. ```python import requests url = "https://livetiming.formula1.com/static/2024/2024-07-28_Belgian_Grand_Prix/2024-07-28_Race/TimingDataF1.json" response = requests.get(url) data = response.json() print(data) ``` -------------------------------- ### Get Base Information Index Source: http://livef1.goktugocal.com/livetimingf1/f1_data.html Retrieves a list of available years and their corresponding API paths. This is the starting point for accessing historical or current season data. ```json { "Years": [ { "Year": 2024, "Path": "2024/" } ] } ``` -------------------------------- ### Get Specific Session Directly - Python Source: http://livef1.goktugocal.com/user_guide/historical_data.html Use this to retrieve a specific historical F1 session by providing the season year and unique identifiers for the meeting and session type. Ensure you have the livef1 package installed. ```python import livef1 # Get specific session directly race = livef1.get_session( season=2024, meeting_identifier="Spa", # Circuit/Location name session_identifier="Race" # Session type ) ``` -------------------------------- ### Initialize RealF1Client Source: http://livef1.goktugocal.com/_modules/livef1/adapters/realtime_client.html Initializes the RealF1Client with specified topics and optional logging configurations. Raises an ArgumentError if topics are not a string or list. ```python def __init__( self, topics, log_file_name = None, log_file_mode = "w", ): self._connection_url = urljoin(BASE_URL, SIGNALR_ENDPOINT) self.headers = { 'User-agent': 'BestHTTP', 'Accept-Encoding': 'gzip, identity', 'Connection': 'keep-alive, Upgrade'} if isinstance(topics, str): self.topics = [topics] elif isinstance(topics, list): self.topics = topics else: raise ArgumentError("You need to give list of topics you want to subscribe") self._log_file_name = log_file_name self._log_file_mode = log_file_mode self._handlers = {} if self._log_file_name: self._log_file = open(self._log_file_name, self._log_file_mode) @self.callback("default logger") async def print_callback( records ): for topic, data in records.items(): for record in data: await self._file_logger(f"{topic} > {record}") ``` -------------------------------- ### Navigate to Project Directory Source: http://livef1.goktugocal.com/_sources/getting_started/installation.rst.txt Change your current directory to the cloned LiveF1 project folder. ```bash cd LiveF1 ``` -------------------------------- ### RealF1Client Initialization Source: http://livef1.goktugocal.com/_modules/livef1/adapters/realtime_client.html Initializes the RealF1Client with specified topics and optional logging configurations. ```APIDOC ## RealF1Client(topics, log_file_name=None, log_file_mode='w') ### Description A client for managing real-time Formula 1 data streaming. ### Parameters - **topics** (str or list) - Topic(s) to subscribe to for live updates. - **log_file_name** (str, optional) - Name of the log file (default is None). - **log_file_mode** (str, optional) - Mode for opening the log file (default is "w"). ``` -------------------------------- ### Get Table Data from Session Source: http://livef1.goktugocal.com/_modules/livef1/models/session.html Retrieves table data, handling both single string names and lists of names. It delegates to the main 'get' method. ```python def get_table( self, dataNames, level = "bronze", parallel: bool = False, force: bool = False ): if isinstance(dataNames, str): return self.get( dataNames, level=level, parallel= parallel, force = force) elif isinstance(dataNames, list): res = self.get( dataNames, level=level, parallel= parallel, force = force ) return {name:table for name, table in res.items()} else: return None ``` -------------------------------- ### RealF1Client Initialization and Callback Registration Source: http://livef1.goktugocal.com/_modules/livef1/adapters/realtime_client.html Demonstrates how to initialize the RealF1Client and register a custom callback function for incoming messages. ```APIDOC ## RealF1Client ### Description Initializes the RealF1Client to connect to the live timing stream and receive data. ### Parameters - **topics** (list[str]) - A list of topics to subscribe to. - **log_file_name** (str, optional) - The name of the file to log incoming data to. ### Example ```python from livef1.adapters.realtime_client import RealF1Client client = RealF1Client( topics = ["CarData.z", "SessionInfo"], log_file_name="./output.json" ) @client.callback("new one") async def print_callback(records): print(records) client.run() ``` ``` -------------------------------- ### Aggregate and Finalize Lap Data Source: http://livef1.goktugocal.com/_modules/livef1/data_processing/silver_functions.html Combines lap data from all drivers, calculates lap start dates, and adjusts lap start times. Deletes invalid laps and adds session and driver information. ```python # Aggregate all laps data of the driver laps_df = pd.DataFrame(laps) laps_df["DriverNo"] = driver_no if "LapStartTime" in laps_df.columns: laps_df = add_track_status(laps_df, df_track) all_laps.append(laps_df) all_laps_df = pd.concat(all_laps, ignore_index=True) new_ts = (all_laps_df["LapStartTime"] + all_laps_df["LapTime"]).shift(1) all_laps_df["LapStartTime"] = (new_ts.isnull() * all_laps_df["LapStartTime"]) + new_ts.fillna(timedelta(0)) all_laps_df["LapStartDate"] = (all_laps_df["LapStartTime"] + session.first_datetime).fillna(session.session_start_datetime) all_laps_df["LapStartTime"] = all_laps_df["LapStartTime"].fillna(all_laps_df.iloc[1].LapStartTime - (all_laps_df.iloc[1].LapStartDate - all_laps_df.iloc[0].LapStartDate)) # Delete laps all_laps_df = delete_laps(all_laps_df, df_rcm) # Add session data all_laps_df["SessionKey"] = sessionKey # Add driver data all_laps_df["Driver"] = all_laps_df["DriverNo"].map(session.drivers) ``` -------------------------------- ### Example Logging in Client Callback Source: http://livef1.goktugocal.com/user_guide/logging_config.html Demonstrates how to use the logger within a RealF1Client callback. Includes setting the log level to DEBUG and logging messages at different levels (debug, info, error) during data processing. ```python from livef1.adapters.realtime_client import RealF1Client from livef1.utils.logger import logger, set_log_level import logging # Enable debug logging set_log_level('DEBUG') # Initialize client client = RealF1Client(topics=["CarData.z"]) @client.callback("logging_example") async def handle_data(records): logger.debug(f"Received {len(records)} records") logger.info("Processing new data batch") try: # Process records process_records(records) except Exception as e: logger.error(f"Error processing records: {e}") ``` -------------------------------- ### LivetimingF1adapters GET Request Source: http://livef1.goktugocal.com/_modules/livef1/adapters/livetimingf1_adapter.html Sends a GET request to a specified endpoint, handling timeouts, connection errors, and HTTP errors. Decodes the response content as UTF-8. Raises specific exceptions for different error types. ```python req_url = urllib.parse.urljoin(self.url, endpoint) # Build the full request URL logger.debug(f"Sending GET request to URL: {req_url}") response = requests.get( url=req_url, headers=header, timeout=300 # Timeout added for robustness ) response.raise_for_status() # Decode response try: res_text = response.content.decode('utf-8-sig') except UnicodeDecodeError as decode_err: logger.error(f"Failed to decode response: {decode_err}", exc_info=True) raise DataDecodingError(f"Failed to decode response: {decode_err}") from decode_err return res_text except requests.exceptions.Timeout as timeout_err: logger.error(f"Request timed out for URL: {req_url}", exc_info=True) raise TimeoutError(f"Request timed out: {timeout_err}") from timeout_err except requests.exceptions.ConnectionError as conn_err: logger.error(f"Connection failed for URL: {req_url}", exc_info=True) raise ConnectionError(f"Connection failed: {conn_err}") from conn_err except requests.exceptions.HTTPError as http_err: if response.status_code in [403,404]: logger.error(f"Endpoint not found: {req_url}", exc_info=True) raise InvalidEndpointError(f"Endpoint not found: {endpoint}") from http_err else: logger.error(f"HTTP error occurred for URL {req_url}: {http_err}", exc_info=True) raise AdapterError(f"HTTP error occurred: {http_err}") from http_err except Exception as e: logger.critical(f"Unexpected error for URL {req_url}: {e}", exc_info=True) raise AdapterError(f"An unexpected error occurred: {e}") from e ``` -------------------------------- ### Initialize RealF1Client Source: http://livef1.goktugocal.com/_sources/user_guide/realtime_data.rst.txt Instantiate the RealF1Client to connect to the active F1 session and stream data. Specify desired topics and optionally a log file for incoming data. ```python from livef1.adapters.realtime_client import RealF1Client client = RealF1Client( topics=["CarData.z", "SessionInfo"], log_file_name="./output.json" # Optional: log incoming data ) ``` -------------------------------- ### Get Session Details Source: http://livef1.goktugocal.com/_sources/livetimingf1/f1_data.rst.txt Contains detailed information about the session. ```APIDOC ## GET /static/{year}/{meeting_path}/{session_path}/SessionInfo.json ### Description Contains detailed information about the session. ### Endpoint https://livetiming.formula1.com/static/2024/2024-06-23_Spanish_Grand_Prix/2024-06-23_Race/SessionInfo.json ### Response #### Success Response (200) - **[Fields will vary based on the actual session data]** ### Response Example ```json { "SessionName": "Race", "SessionType": "Race", "Track": { "Name": "Circuit de Barcelona-Catalunya", "Location": "Montmelo, Barcelona", "Country": "Spain" } } ``` ``` -------------------------------- ### Get Yearly Sessions Source: http://livef1.goktugocal.com/_sources/livetimingf1/f1_data.rst.txt Lists races and sessions for a specified year. ```APIDOC ## GET /static/{year}/Index.json ### Description Lists races and sessions for the specified year. ### Endpoint https://livetiming.formula1.com/static/2024/Index.json ### Response #### Success Response (200) - **Year** (Integer) - The year of the data - **Meetings** (Array) - List of races and associated sessions - **Key** (Integer) - Unique identifier for the meeting - **Name** (String) - Name of the meeting - **Sessions** (Array) - List of sessions for the meeting ### Response Example ```json { "Year": 2024, "Meetings": [ { "Key": 1238, "Name": "Spanish Grand Prix", "Sessions": [ { "Key": 9539, "Type": "Race", "Path": "2024/2024-06-23_Spanish_Grand_Prix/2024-06-23_Race/" } ] } ] } ``` ``` -------------------------------- ### Set up SignalR Connection and Handlers Source: http://livef1.goktugocal.com/_modules/livef1/adapters/realtime_client.html Configures the SignalR connection, registers the 'Streaming' hub, and sets up default message handlers for incoming methods. ```python # Create connection self._connection = Connection(self._connection_url, session=self._create_session()) # Register hub hub = self._connection.register_hub('Streaming') # Set default message handler for method, handler in self._handlers.items(): hub.client.on(method, handler) # Subscribe topics in interest hub.server.invoke("Subscribe", self.topics) # Start the client loop = asyncio.get_event_loop() executor = concurrent.futures.ThreadPoolExecutor() await loop.run_in_executor(executor, self._connection.start) ``` -------------------------------- ### Extrapolated Clock Source: http://livef1.goktugocal.com/_sources/livetimingf1/data_topics.rst.txt Get the current extrapolated time data for the ongoing session. ```APIDOC ## GET /static/{year}/{event_name}/ExtrapolatedClock.json ### Description Retrieves the current session time, including remaining time and extrapolation status. ### Method GET ### Endpoint /static/{year}/{event_name}/ExtrapolatedClock.json ### Response #### Success Response (200) - **Utc** (string) - The current time in UTC format. - **Remaining** (string) - The time remaining in the session (format: HH:MM:SS). - **Extrapolating** (boolean) - Indicates if the clock data is being extrapolated. ### Response Example ```json { "Utc": "2024-07-28T14:25:45.007Z", "Remaining": "00:38:07", "Extrapolating": true } ``` ``` -------------------------------- ### Registering Silver and Gold Tables Together Source: http://livef1.goktugocal.com/_sources/user_guide/medallion_architecture.rst.txt Demonstrates creating a Silver table 'SectorDiff' from a default Silver table 'laps', and then a Gold table 'SectorLeaders' from the newly created 'SectorDiff' table. Ensure to set gold=True when calling session.generate(). ```python import livef1 session = livef1.get_session( 2024, "Belgian", "Qualifying" ) @session.create_silver_table( table_name = "SectorDiff", source_tables = ["laps"], # This time we source from a default silver table to create a silver table. include_session = True ) def sector_diff(session, laps): df = laps.groupby("DriverNo")[["Sector1_Time","Sector2_Time","Sector3_Time"]].min().reset_index() df["sector1_diff"] = (df["Sector1_Time"] - df["Sector1_Time"].min()).dt.total_seconds() df["sector2_diff"] = (df["Sector2_Time"] - df["Sector2_Time"].min()).dt.total_seconds() df["sector3_diff"] = (df["Sector3_Time"] - df["Sector3_Time"].min()).dt.total_seconds() df["DriverName"] = df["DriverNo"].map(lambda x: session.drivers[x].FullName) return df @session.create_gold_table( table_name = "SectorLeaders", source_tables = ["SectorDiff"], # This time we source from a newly registered silver table to create a gold table. include_session = True ) def sector_diff(session, SectorDiff): return SectorDiff.iloc[SectorDiff[["sector1_diff","sector2_diff","sector3_diff"]].idxmin().values) # Generate all tables session.generate(silver=True, gold=True) # We should set gold as True. ``` -------------------------------- ### Get Session Topics Source: http://livef1.goktugocal.com/_sources/livetimingf1/f1_data.rst.txt Provides available data topics for a specific session. ```APIDOC ## GET /static/{year}/{meeting_path}/{session_path}/Index.json ### Description Provides available data topics for a specific session. ### Endpoint https://livetiming.formula1.com/static/2024/2024-06-23_Spanish_Grand_Prix/2024-06-23_Race/Index.json ### Response #### Success Response (200) - **Feeds** (Object) - Contains different data feed categories - **SessionInfo** (Object) - Details about the session - **KeyFramePath** (String) - Path to the keyframe data - **StreamPath** (String) - Path to the data stream - **TrackStatus** (Object) - Details about the track status ### Response Example ```json { "Feeds": { "SessionInfo": { "KeyFramePath": "SessionInfo.json", "StreamPath": "SessionInfo.jsonStream" }, "TrackStatus": { "KeyFramePath": "TrackStatus.json", "StreamPath": "TrackStatus.jsonStream" } } } ``` ``` -------------------------------- ### Complete Historical Data Analysis Example Source: http://livef1.goktugocal.com/user_guide/historical_data.html Demonstrates a full workflow for analyzing historical race data. It includes fetching session data, generating processed data, extracting lap times and telemetry, and analyzing the fastest laps per driver. ```python import livef1 # Get a specific race session race = livef1.get_session( season=2023, meeting_identifier="Monaco", session_identifier="Race" ) # Generate processed data race.generate() # Get lap times and telemetry laps_data = race.laps telemetry = race.carTelemetry # Analyze fastest laps fastest_laps = laps_data.sort_values('LapTime').groupby('DriverNumber').first() print("Fastest laps by driver:\n****************") print(fastest_laps[['LapTime', 'LapNumber']]) ``` -------------------------------- ### Print Topic Names and Descriptions Source: http://livef1.goktugocal.com/_modules/livef1/models/session.html Prints the key and description for each topic available in the session. It ensures topic names are loaded first by calling `get_topic_names` if necessary. ```python if not hasattr(self, "topic_names_info"): self.get_topic_names() logger.debug(f"Printing topic names and descriptions for the session: {self.meeting.name}: {self.name}") for topic in self.topic_names_info: print(self.topic_names_info[topic]["key"], ": \n\t", self.topic_names_info[topic]["description"]) ``` -------------------------------- ### livetimingF1_request Function Source: http://livef1.goktugocal.com/api_reference/livetimingf1_adapter.html Wrapper function to perform a GET request to the Livetiming F1 API. ```APIDOC ## livetimingF1_request(url) ### Description Wrapper function to perform a GET request to the Livetiming F1 API. ### Parameters - **url** (str) - Required - The full URL to request. ### Returns - dict: Parsed JSON response from the API. ``` -------------------------------- ### Initialize LivetimingF1adapters Source: http://livef1.goktugocal.com/_modules/livef1/adapters/livetimingf1_adapter.html Initializes the adapter with the base URL for the F1 Livetiming API. The base URL is constructed using BASE_URL and STATIC_ENDPOINT constants. ```python self.url = urllib.parse.urljoin(BASE_URL, STATIC_ENDPOINT) # Base URL for F1 Livetiming API ``` -------------------------------- ### Get Base Information Source: http://livef1.goktugocal.com/_sources/livetimingf1/f1_data.rst.txt Retrieves a list of available years and their corresponding data paths. ```APIDOC ## GET /static/Index.json ### Description Provides a list of available years and their corresponding paths. ### Endpoint https://livetiming.formula1.com/static/Index.json ### Response #### Success Response (200) - **Years** (Array) - List of available years and paths - **Year** (Integer) - The year of the data - **Path** (String) - Path to access the year-specific data ### Response Example ```json { "Years": [ { "Year": 2024, "Path": "2024/" } ] } ``` ``` -------------------------------- ### Get Laps Data Source: http://livef1.goktugocal.com/api_reference/models.html Retrieves lap data. Logs a message if the data has not yet been generated. ```python session.get_laps() ``` -------------------------------- ### print_topic_names(_urljoin(session.full_path_ , _session.topic_names_info[dataName][dataType])_ , _stream=stream_) Source: http://livef1.goktugocal.com/api_reference/models.html Prints the key and description for each topic available in the topic_names_info attribute. Fetches topic info if not already populated. ```APIDOC ## print_topic_names(_urljoin(session.full_path_ , _session.topic_names_info[dataName][dataType])_ , _stream=stream_) ### Description This method prints the key and description for each topic available in the topic_names_info attribute. If the topic_names_info attribute is not already populated, it fetches the data using the get_topic_names method. ### Notes * The method assumes the topic_names_info attribute is a dictionary where each key represents a topic, and its value is another dictionary containing key and description. - The get_topic_names method is called if topic_names_info is not already populated. ### Examples The output would be: ``` T1 : Description for topic 1 T2 : Description for topic 2 ``` ``` -------------------------------- ### Register Silver and Gold Tables Together Source: http://livef1.goktugocal.com/user_guide/medallion_architecture.html Demonstrates registering both Silver and Gold layer tables. The 'SectorDiff' Silver table sources from a default table ('laps'), and the 'SectorLeaders' Gold table sources from the newly created 'SectorDiff' table. ```python import livef1 session = livef1.get_session( 2024, "Belgian", "Qualifying" ) @session.create_silver_table( table_name = "SectorDiff", source_tables = ["laps"], # This time we source from a default silver table to create a silver table. include_session = True ) def sector_diff(session, laps): df = laps.groupby("DriverNo")[["Sector1_Time","Sector2_Time","Sector3_Time"]].min().reset_index() df["sector1_diff"] = (df["Sector1_Time"] - df["Sector1_Time"].min()).dt.total_seconds() df["sector2_diff"] = (df["Sector2_Time"] - df["Sector2_Time"].min()).dt.total_seconds() df["sector3_diff"] = (df["Sector3_Time"] - df["Sector3_Time"].min()).dt.total_seconds() df["DriverName"] = df["DriverNo"].map(lambda x: session.drivers[x].FullName) return df @session.session.create_gold_table( table_name = "SectorLeaders", source_tables = ["SectorDiff"], # This time we source from a newly registered silver table to create a gold table. include_session = True ) def sector_diff(session, SectorDiff): return SectorDiff.iloc[SectorDiff[["sector1_diff","sector2_diff","sector3_diff"]].idxmin().values] # Generate all tables session.generate(silver=True, gold=True) # We should set gold as True. ``` -------------------------------- ### livetimingF1_request Source: http://livef1.goktugocal.com/_modules/livef1/adapters/livetimingf1_adapter.html A wrapper function to perform a GET request to the Livetiming F1 API and parse the JSON response. ```APIDOC ## livetimingF1_request ### Description This function initializes the `LivetimingF1adapters` and uses its `get` method to fetch data from a given URL. It then parses the response as JSON. ### Method GET (internal) ### Endpoint [URL provided as parameter] ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python api_url = "https://api.example.com/f1/livetiming/data" parsed_data = livetimingF1_request(api_url) ``` ### Response #### Success Response (200) - **dict**: A dictionary containing the parsed JSON response from the API. #### Response Example ```json { "status": "success", "data": [ {"id": 1, "value": "example"} ] } ``` ### Error Handling - **ParsingError**: If the response content cannot be parsed as JSON. ``` -------------------------------- ### Configure LiveF1 Logger Source: http://livef1.goktugocal.com/_modules/livef1/utils/logger.html Sets up the main 'livef1' logger with console and file handlers. The logger level is initially set to INFO, but can be overridden by the DEBUG environment variable. ```python import logging import os # Logger setup # LOG_LEVEL = logging.DEBUG if os.getenv("DEBUG", "False").lower() == "true" else logging.INFO LOG_LEVEL = logging.INFO STREAM_LOG_FORMAT = "% (asctime)s - %(message)s" FILE_LOG_FORMAT = "% (asctime)s - %(name)s - %(levelname)s - %(message)s" # Configure logger logger = logging.getLogger("livef1") logger.setLevel(LOG_LEVEL) # Handlers console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter(STREAM_LOG_FORMAT,"%H:%M:%S")) file_handler = logging.FileHandler("livef1.log") file_handler.setFormatter(logging.Formatter(FILE_LOG_FORMAT,"%Y-%m-%d %H:%M:%S")) # Add handlers to logger logger.addHandler(console_handler) logger.addHandler(file_handler) ``` -------------------------------- ### Add Custom Handler Source: http://livef1.goktugocal.com/_sources/user_guide/logging_config.rst.txt Extend the logger by adding custom handlers. This example adds a StreamHandler with a custom formatter. ```python from livef1.utils.logger import logger import logging # Create custom handler custom_handler = logging.StreamHandler() custom_handler.setFormatter(logging.Formatter('%(asctime)s - %(message)s')) logger.addHandler(custom_handler) ``` -------------------------------- ### Get Car Telemetry Data Source: http://livef1.goktugocal.com/api_reference/models.html Retrieves car telemetry data. Logs a message if the data has not yet been generated. ```python session.get_car_telemetry() ``` -------------------------------- ### Get Session Data and Process It Source: http://livef1.goktugocal.com/user_guide/data_models.html Illustrates how to retrieve a specific F1 session (e.g., Race) and access its raw data, generate processed tables, or access processed data like laps and telemetry. ```python # Get specific session session = livef1.get_session( season=2024, meeting_identifier="Monaco", session_identifier="Race" ) # Load raw data telemetry = session.get_data("CarData.z") # Generate processed tables session.generate(silver=True) # Access processed data laps = session.laps telemetry = session.carTelemetry ``` -------------------------------- ### Register Custom Silver Tables Source: http://livef1.goktugocal.com/user_guide/medallion_architecture.html Demonstrates the import statement for registering custom Silver layer tables. The actual registration logic would follow this import. ```python import livef1 ``` -------------------------------- ### Clone LiveF1 Repository Source: http://livef1.goktugocal.com/_sources/getting_started/installation.rst.txt Clone the LiveF1 repository from GitHub to get the latest development version or to contribute to the project. ```bash git clone https://github.com/goktugocal/LiveF1.git ``` -------------------------------- ### Get Yearly Sessions Index Source: http://livef1.goktugocal.com/_sources/livetimingf1/f1_data.rst.txt Fetch a list of races and sessions for a specific year, such as 2024, from the F1 LiveTiming API. ```json { "Year": 2024, "Meetings": [ { "Key": 1238, "Name": "Spanish Grand Prix", "Sessions": [ { "Key": 9539, "Type": "Race", "Path": "2024/2024-06-23_Spanish_Grand_Prix/2024-06-23_Race/" }, // ...other sessions ] }, // ...other meetings ] } ``` -------------------------------- ### Get Base Information Index Source: http://livef1.goktugocal.com/_sources/livetimingf1/f1_data.rst.txt Retrieve a list of available years and their corresponding data paths from the F1 LiveTiming API. ```json { "Years": [ { "Year": 2024, "Path": "2024/" } ] } ``` -------------------------------- ### Database Handler for Real-Time Data Source: http://livef1.goktugocal.com/_sources/user_guide/realtime_data.rst.txt An example class demonstrating how to store incoming real-time F1 data into an SQLite database. It includes table creation and data insertion methods, handling telemetry data with timestamps and driver information. ```python import sqlite3 from datetime import datetime import json class F1Database: def __init__(self, db_name="f1_data.db"): self.conn = sqlite3.connect(db_name) self.create_tables() def create_tables(self): cursor = self.conn.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS telemetry_data ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp TEXT, topic TEXT, driver_number INTEGER, data JSON ) ''') self.conn.commit() def insert_data(self, timestamp, topic, driver_number, data): cursor = self.conn.cursor() cursor.execute(''' INSERT INTO telemetry_data (timestamp, topic, driver_number, data) VALUES (?, ?, ?, ?) ''', (timestamp, topic, driver_number, json.dumps(data))) self.conn.commit() ``` -------------------------------- ### Parallel vs Sequential Data Loading Source: http://livef1.goktugocal.com/_sources/user_guide/historical_data.rst.txt Demonstrates how to load multiple data topics from a session, either in parallel (default) or sequentially. Use parallel loading for multiple large datasets to improve performance. ```python # Load multiple topics in parallel (default behavior) data = session.get_data( ["CarData.z", "Position.z", "SessionStatus"] ) ``` ```python # Load topics sequentially (parallel disabled) data = session.get_data( ["CarData.z", "Position.z", "SessionStatus"], parallel=False ) ``` -------------------------------- ### add_distance_to_lap Source: http://livef1.goktugocal.com/api_reference/medallion_arch.html Calculates the cumulative distance covered by a car during a lap based on its speed and timestamp, adjusting for starting line coordinates and direction. ```APIDOC ## add_distance_to_lap ### Description Calculates the cumulative distance covered by a car during a lap based on its speed and timestamp. Adjusts the distance based on the starting line coordinates and direction. ### Parameters - **lap_df** (pd.DataFrame): DataFrame containing lap data with columns ‘speed’, ‘timestamp’, ‘X’, and ‘Y’. - **start_x** (float): X-coordinate of the starting line. - **start_y** (float): Y-coordinate of the starting line. - **x_coeff** (float): Coefficient for determining direction along the X-axis. - **y_coeff** (float): Coefficient for determining direction along the Y-axis. ### Returns - **pd.DataFrame**: Updated DataFrame with a new ‘Distance’ column representing the cumulative distance. ``` -------------------------------- ### Print Session.SectorLeaders Head Source: http://livef1.goktugocal.com/_sources/user_guide/medallion_architecture.rst.txt Prints the first few rows of the 'SectorLeaders' table, showing the drivers with the minimum sector times. ```python print(session.SectorLeaders.head()) ``` -------------------------------- ### RealF1Client Methods Source: http://livef1.goktugocal.com/api_reference/realtime_client.html Provides an overview of the methods available on the RealF1Client class for managing real-time data streams. ```APIDOC ## RealF1Client ### Description Represents a client for receiving real-time data. It handles message processing and callbacks. ### Methods #### `callback()` ##### Description Registers a callback function to be executed when a new message is received. ##### Parameters - **callback_func** (function) - Required - The function to be called with the received message. #### `on_message()` ##### Description Internal method to process incoming messages. This method is typically called by the underlying transport layer. ##### Parameters - **message** (bytes) - Required - The raw message data received. #### `run()` ##### Description Starts the real-time client and begins listening for incoming messages. This method will block until the client is stopped or an error occurs. ##### Parameters None ``` -------------------------------- ### Fetch Session Info using Python Source: http://livef1.goktugocal.com/_sources/livetimingf1/data_topics.rst.txt This Python script demonstrates how to fetch and parse the SessionInfo.json file from the Live Timing F1 API using the urllib library. ```python from urllib.request import urlopen import json url = "https://livetiming.formula1.com/static/2024/2024-07-28_Belgian_Grand_Prix/2024-07-28_Race/SessionInfo.json" response = urlopen(url) data = json.loads(response.read().decode('utf-8')) print(data) ``` -------------------------------- ### Initialize livef1SessionETL with Session and Function Map Source: http://livef1.goktugocal.com/_modules/livef1/data_processing/etl.html Initializes the ETL class with a session object and a mapping of data titles to parsing functions. Ensure the function_map is correctly defined before instantiation. ```python class livef1SessionETL: def __init__(self, session): self.session = session self.function_map = function_map ``` -------------------------------- ### get_driver(_identifier : str_) Source: http://livef1.goktugocal.com/api_reference/models.html Get a specific driver by their number, name, or short name. Returns the Driver object or None if not found. ```APIDOC ## get_driver(_identifier : str_) → Driver ### Description Get a specific driver by their number, name, or short name. ### Parameters #### Path Parameters - **identifier** (str) - Required - The driver’s racing number, full name, or short name. ### Returns Driver The Driver object for the specified identifier, or None if not found. ``` -------------------------------- ### Get Multiple Topics Data in Parallel Source: http://livef1.goktugocal.com/api_reference/models.html Retrieve data for multiple topics simultaneously. This is the default behavior when a list of topics is provided. ```python data = session.get_data(["CarData.z", "Position.z", "SessionStatus"]) ```