# Technical Documentation: theOehrly/Fast-F1

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/theOehrly/Fast-F1)

### Overview (`README.md`)

<h1 align="center">
<img src="docs/_static/banner.png" width="400">
</h1><br>
A python package for accessing and analyzing Formula 1 results,
schedules, timing data and telemetry.

## Main Features

- Access to F1 timing data, telemetry, sessions results and more
- Full support for the Ergast compatible [jolpica-f1](https://github.com/jolpica/jolpica-f1/blob/main/docs/README.md) API to access current and
  historical F1 data
- All data is provided in the form of extended Pandas DataFrames to make
  working with the data easy while having powerful tools available
- Adds custom functions to the Pandas objects specifically to make working
  with F1 data quick and simple
- Integration with Matplotlib to facilitate data visualization
- Implements caching for all API requests to speed up your scripts


## Installation

It is recommended to install FastF1 using `pip`:

```commandline
pip install fastf1
```

Alternatively, a wheel or a source distribution can be downloaded from Pypi.

You can also install using `conda`:

```commandline
conda install -c conda-forge fastf1
```

#### Installation in Pyodide, JupyterLite and other WASM-based environments

FastF1 should be mostly compatible with Pyodide and other WASM-based 
environments, although this is not extensively tested. Currently, the 
installation and usage require some additional steps. You can find more 
information and a guide in
[this external repository](https://github.com/f1datajunkie/jupyterlite-fastf1)
and the discussion in [this issue](https://github.com/theOehrly/Fast-F1/issues/667).

### Third-party packages

- R package that wraps FastF1: https://cran.r-project.org/package=f1dataR

Third-party packages are not directly related to the FastF1 project. Questions 
and suggestions regarding these packages need to be directed at their 
respective maintainers.

## Documentation

The official documentation can be found here:
[docs.fastf1.dev](https://docs.fastf1.dev)


## Supporting the Project

If you want to support the continuous development of FastF1, you can sponsor me
on GitHub or buy me a coffee.

https://github.com/sponsors/theOehrly

<a href="https://www.buymeacoffee.com/fastf1" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a>


## Notice

FastF1 and this website are unofficial and are not associated in any way with
the Formula 1 companies. F1, FORMULA ONE, FORMULA 1, FIA FORMULA ONE WORLD
CHAMPIONSHIP, GRAND PRIX and related marks are trade marks of Formula One
Licensing B.V.

---

### Index (`docs/index.rst`)

######################
Introduction to FastF1
######################

.. toctree::
   :hidden:

   getting_started/index
   gen_modules/examples_gallery/index
   api_reference/index
   data_reference/index
   changelog/index
   contributing/index

FastF1 gives you access to F1 lap timing, car telemetry and position,
tyre data, weather data, the event schedule and session results.


.. raw:: html

    <style>
      .doc-tile-container {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        gap: 16px;
        margin: 30px 0;
      }
      .doc-tile {
        width: 165px;
        box-shadow: 0 4px 8px var(--pst-color-shadow, rgba(0, 0, 0, 0.1));
        border-radius: 5px;
        padding: 10px 16px 10px 16px;
        text-align: center;
        background-color: var(--pst-color-surface, var(--pst-color-background, white));
        transition: transform 0.3s, box-shadow 0.3s;
        text-decoration: none !important;
        color: inherit !important;
        display: block;
      }
      .doc-tile:hover {
        transform: translateY(-5px);
        box-shadow: 0 8px 16px var(--pst-color-shadow, rgba(0, 0, 0, 0.2));
      }
      .doc-tile h2 {
        margin-top: 0;
        font-size: 1.2rem;
        margin-bottom: 5px;
        color: var(--pst-color-text-base);
      }
      .doc-tile p {
        margin: 0;
        font-size: 0.9rem;
        color: var(--pst-color-text-muted, #666);
      }
      .doc-tile-icon {
        font-size: 3rem;
        margin-bottom: 15px;
        color: #e74c3c;
      }
    </style>

    <div class="doc-tile-container">

      <a href="getting_started/index.html" class="doc-tile">
        <div class="doc-tile-icon">📚</div>
        <h2>Getting<br>Started</h2>
        <p>Examples and tutorials to help you get started</p>
      </a>

      

      <a href="api_reference/index.html" class="doc-tile">
        <div class="doc-tile-icon">🔍</div>
        <h2>API<br>Reference</h2>
        <p>Documentation of classes and functions</p>
      </a>

      <a href="data_reference/index.html" class="doc-tile">
        <div class="doc-tile-icon">📊</div>
        <h2>Data<br>Reference</h2>
        <p>Documentation of the available data</p>
      </a>

       <a href="gen_modules/examples_gallery/index.html" class="doc-tile">
         <div class="doc-tile-icon">🖼️</div>
         <h2>Example<br>Gallery</h2>
         <p>Examples showing FastF1's capabilities</p>
       </a>

      <a href="contributing/index.html" class="doc-tile">
        <div class="doc-tile-icon">⚙️</div>
        <h2>Development<br>&nbsp</h2>
        <p>How to contribute and help improve FastF1</p>
      </a>

    </div>



========
Features
========

- Access to F1 timing data, telemetry, sessions results and more
- Full support for the Ergast compatible `jolpica-f1 <https://github.com/jolpica/jolpica-f1/blob/main/docs/README.md>`_ API to access current and
  historical F1 data
- All data is provided in the form of extended Pandas DataFrames to make
  working with the data easy while having powerful tools available
- Adds custom functions to the Pandas objects specifically to make working
  with F1 data quick and simple
- Integration with Matplotlib to facilitate data visualization
- Implements caching for all API requests to speed up your scripts


..
    To get a quick overview over how to use FastF1, check out
    :doc:`examples/index` or the :doc:`gen_modules/examples_gallery/index`.

    Note that FastF1 handles big chunks of data (~50-100mb per session). To improve
    performance, data is per default cached locally. The default placement
    of the cache is operating system specific. A custom location can be set if
    desired. For more information see :class:`~fastf1.req.Cache`.


=================
Third-party Tools
=================

These packages are not directly related to the FastF1 project. Questions and
suggestions regarding these packages need to be directed at their respective
maintainers.


SDKs
----

- **f1dataR**: R package that wraps FastF1 (https://cran.r-project.org/package=f1dataR)


Websites
--------

- **GP Tempo**: Web App for exploring F1 Telemetry Data (https://www.gp-tempo.com/)
- **Armchair Strategist**: Strategy dashboard for all F1 races since 2018 (https://armchair-strategist.dev/)


========================================================
Questions, Contacting the Maintainer and Code of Conduct
========================================================

For questions that may be of interest to the whole community, please use the
Github `Discussions <https://github.com/theOehrly/Fast-F1/discussions>`_
section to ask for help. This includes general support questions.

In case of questions that you need to discuss privately, feel free to contact
me via email at oehrly@mailbox.org. Any requests to this address will be
treated with confidentiality, if desired. **Do not use this email address for
general support requests! Such requests will likely be ignored.**

FastF1 has a `Code of Conduct <https://github.com/theOehrly/Fast-F1/blob/main/CODE_OF_CONDUCT.md>`_.
Complaints about a perceived breach of this code of conduct should be sent to
oehrly@mailbox.org, in almost all cases. Please refer to the Code of Conduct,
available through the main page of the GitHub repository (or click
`here <https://github.com/theOehrly/Fast-F1/blob/main/CODE_OF_CONDUCT.md>`_),
for information on how breaches are reported, how the
Code of Conduct is enforced and what values FastF1 encourages.


======
Notice
======

FastF1 and this website are unofficial and are not associated in any way with
the Formula 1 companies. F1, FORMULA ONE, FORMULA 1, FIA FORMULA ONE WORLD
CHAMPIONSHIP, GRAND PRIX and related marks are trade marks of Formula One
Licensing B.V.

---

###  Templates Class Summary Noinherited (`docs/_templates/class_summary_noinherited.rst`)

``{{ name }}``
=======================================================================================================================

.. currentmodule:: {{ module }}

.. autoclass:: {{ objname }}
    :members:
    :autosummary:
    :show-inheritance:

---

###  Templates Function (`docs/_templates/function.rst`)

``{{ name }}``
=======================================================================================================================

.. currentmodule:: {{ module }}

.. auto{{ objtype }}:: {{ objname }}

---

### Api Reference Accounts Auth (`docs/api_reference/accounts_auth.rst`)

.. _`accounts-auth`:

F1TV Account Authentication
===========================

F1TV Account Usage
------------------

FastF1 can require an active F1TV Access/Pro/Premium subscription to access certain data.
Currently, authentication is only required when using the :ref:`livetiming`.
All data that is obtained after the session has ended can be accessed without authentication.

When FastF1 encounters a feature that requires authentication, it will automatically prompt
you to authenticate with your F1TV account if you haven't done so already.

Authentication Workflow
-----------------------

When authentication is required, FastF1 will:

1. Check for an existing valid authentication token
2. If no valid token exists, sign in to your Formula 1 account with the selected sign-in method
3. After successful login, store the authentication token locally
4. Use this token for subsequent data requests

The stored token is independent of the sign-in method that was used to obtain it.


Sign-in Methods
---------------

FastF1 supports two sign-in methods.

``password`` (default)
    FastF1 signs in directly with your Formula 1 account email and password. The credentials
    are read from the environment variables ``F1_USERNAME`` and ``F1_PASSWORD``. If they are
    not set and the session is interactive, you are prompted for them. Your credentials are
    only sent to Formula 1 and are never stored by FastF1.

``browser``
    FastF1 provides a URL that you need to open in a browser to login to F1TV.
    A browser addon is required for FastF1 to perform this login. If you have not already
    installed this addon, you will be redirected to a page that offers download options for
    the addon. You can also visit f1login.fastf1.dev directly. If the addon is installed and
    working correctly, you will be redirected to see a success status message. Else, you will
    be provided with download options for the addon.

    .. note::

        This method is not supported in hosted environments like Google Colab or in
        WebAssembly based environments like Jupyter Lite.

The sign-in method is selected, in order of precedence:

1. by calling :func:`fastf1.set_auth_method` in your script, e.g.
   ``fastf1.set_auth_method('browser')``
2. by setting the environment variable ``FASTF1_AUTH_METHOD`` to ``password`` or ``browser``
3. else, ``password`` is used

.. autofunction:: fastf1.set_auth_method


Command Line Interface
----------------------

FastF1 also provides command line options for managing F1TV authentication:

.. code-block:: console

    python -m fastf1 auth f1tv [--authenticate] [--clear] [--status] [--method {password,browser}]

Options:
  --authenticate  Start the authentication process manually
  --clear         Remove stored authentication token
  --status        Display current authentication status
  --method        Sign-in method to use with ``--authenticate``

---

### Api Reference Cache And Rate Limits (`docs/api_reference/cache_and_rate_limits.rst`)

.. _`rate_limits-caching`:

Rate Limits and Caching
=======================

All HTTP requests that are performed by FastF1 go through its caching and
rate limiting system.

Caching is enabled by default in FastF1 and most of the time, you do not need
to worry about caching at all. It will simply happen automatically in the
background and speed up your programs. Disabling the cache is highly
discouraged and will generally slow down your programs.

Rate limits are applied at all times. Requests that can be served from the
cache do not count towards any rate limits. Having the cache enabled can
therefore virtually increase the rate limits.

When rate limits are exceeded, FastF1 will either...

- throttle the rate of requests, if small delays are sufficient to stay within
  the limit (soft rate limit)

- raise a :class:`fastf1.exceptions.RateLimitExceededError` (hard rate limit)


Rate Limits
-----------

ToDo explain rate limits


Cache Configuration
-------------------

.. currentmodule:: fastf1


.. autoclass:: Cache
    :members:
    :undoc-members:
    :autosummary:

---

### Api Reference Circuit Info (`docs/api_reference/circuit_info.rst`)

.. _circuit_info:

Circuit Information
===================

.. autoclass:: fastf1.mvapi.CircuitInfo
  :members:

---

### Api Reference Deprecated Legacy (`docs/api_reference/deprecated_legacy.rst`)

.. _deprecated-legacy-api:

Deprecated Legacy API
=====================

.. toctree::

    legacy/f1_api


.. toctree::

    legacy/legacy

---

### Api Reference Ergast (`docs/api_reference/ergast.rst`)

Ergast API Interface
====================

See :ref:`jolpica`

---

### Api Reference Events (`docs/api_reference/events.rst`)

.. _event-schedule:

Event Schedule
==============

.. currentmodule:: fastf1.events

Events and the Event Schedule are represented using the following objects.
To access schedule data, see :ref:`loading-data`.

.. autosummary::
    :toctree: api_autogen/
    :template: class_summary_noinherited.rst

    EventSchedule
    Event


The :class:`EventSchedule` provides information about past and upcoming
Formula 1 events.

An :class:`Event` can be a race weekend or a testing event. Each event
consists of multiple :class:`~fastf1.core.Session`.

The event schedule objects are built on top of pandas'
:class:`pandas.DataFrame` (event schedule) and :class:`pandas.Series` (event).
Therefore, the usual methods of these pandas objects can be used in addition
to the special methods described here.


.. _event-schedule-data:

Event Schedule Data
-------------------

The event schedule and each event provide the following information as
DataFrame columns or Series values:

.. list-table::
   :widths: 20 20 60
   :header-rows: 1

   * - Name
     - Data Type
     - Description
   * - **RoundNumber**
     - :class:`int`
     - The number of the championship round. This is unique for race weekends, while testing events all share the round number zero.
   * - **Country**
     - :class:`str`
     - The country in which the event is held.
   * - **Location**
     - :class:`str`
     - The event location; usually the city or region in which the track is situated.
   * - **OfficialEventName**
     - :class:`str`
     - The official event name as advertised, including sponsor names and stuff.
   * - **EventName**
     - :class:`str`
     - A shorter event name usually containing the country or location but no no sponsor names. This name is required internally for proper api access.
   * - **EventDate**
     - :class:`pd.Timestamp`
     - The events reference date and time. This is used mainly internally. Usually, this is the same as the date of the last session.
   * - **EventFormat**
     - :class:`str`
     - The format of the event. One of 'conventional', 'sprint', 'sprint_shootout', 'sprint_qualifying', 'testing'. See :ref:`event-formats`
   * - **Session[1-5]**
     - :class:`str`
     - The name of the session. One of 'Practice 1', 'Practice 2', 'Practice 3', 'Qualifying', 'Sprint', 'Sprint Shootout' or 'Race'. Testing sessions are considered practice.
   * - **Session[1-5]Date**
     - :class:`pd.Timestamp`
     - The date and time at which the session is scheduled to start or was scheduled to start as timezone-aware local timestamp. (Timezone-aware local timestamps are not available when the ``'ergast'`` backend is used.)
   * - **Session[1-5]DateUtc**
     - :class:`pd.Timestamp`
     - The date and time at which the session is scheduled to start or was scheduled to start as non-timezone-aware UTC timestamp.
   * - **F1ApiSupport**
     - :class:`bool`
     - Denotes whether this session is supported by the official F1 API. Lap timing data and telemetry data can only be loaded if this is true.


.. _event-supported-seasons:

Supported Seasons
.................

FastF1 provides its own event schedule for the 2018 season and all later
seasons. The schedule for all seasons before 2018 is built using data from
the Ergast API. Only limited data is available for these seasons. Usage of the
Ergast API can be enforced for all seasons by setting ``backend='ergast'``,
in which case the same limitations apply for the more recent seasons too.

**Exact scheduled starting times for all sessions**:
Supported starting with the 2018 season.
Starting dates for sessions before 2018 (or when enforcing usage of the Ergast
API) assume that each race weekend was held according to the 'conventional'
schedule (Practice 1/2 on friday, Practice 3/Qualifying on Saturday, Race on
Sunday). A starting date and time can only be provided for the race session.
All other sessions are calculated from this and no starting times can be
provided for these. These assumptions will be incorrect for certain events!

**Testing events**: Supported for the 2020 season and later seasons. Not
supported if usage of the Ergast API is enforced.


.. _event-formats:

Event Formats
.............

- ``"conventional"``: **Practice 1, Practice 2, Practice 3, Qualifying, Race**

- ``"sprint"``: **Practice 1, Qualifying, Practice 2, Sprint, Race**

  This is the original sprint format that was used in some races in 2021 and
  2022. The Qualifying on friday set the grid for the Sprint on saturday.
  The results from the Sprint set the grid for the Race on sunday.

- ``"sprint_shootout"``: **Practice 1, Qualifying, Sprint Shootout, Sprint, Race**

  This format was used in 2023. The Qualifying on friday sets the grid for the
  main Race on sunday. The Sprint Shootout on saturday is held in similar
  fashion to a normal Qualifying session and sets the grid for the Sprint that
  takes place on saturday as well.

- ``"sprint_qualifying"``: **Practice 1, Sprint Qualifying, Sprint, Qualifying,
  Race**

  This format is used starting from 2024. In general, it is similar to the
  previous 'sprint_shootout' format, but the order of the sessions was changed
  and 'Sprint Shootout' is renamed to 'Sprint Qualifying'. This means that
  the Sprint Qualifying on friday is held in similar fashion to a normal
  Qualifying and sets the grid for the Sprint on saturday. The Qualifying later
  on saturday then sets the grid for the race on Sunday.

- ``"testing"``: **no fixed session order**

  usually three practice sessions on three separate days


.. _event-session-identifier:

Session identifiers
...................

Multiple event (schedule) related functions and methods make use of a session
identifier to differentiate between the various sessions of one event.
This identifier can currently be one of the following:

- session name abbreviation: ``'FP1', 'FP2', 'FP3', 'Q', 'S', 'SS', 'SQ',
  'R'``
- full session name: ``'Practice 1', 'Practice 2',
  'Practice 3', 'Sprint', 'Sprint Shootout', 'Sprint Qualifying',
  'Qualifying', 'Race'``;
  provided names will be normalized, so that the name is
  case-insensitive
- number of the session: ``1, 2, 3, 4, 5``

.. note::
    The old ``'sprint'`` event format from 2021 and 2022 originally
    used the name 'Sprint Qualifying' before renaming these sessions to just
    'Sprint'. The official schedule for 2021 now lists all these sessions as
    'Sprint' and FastF1 will therefore return all these sessions as 'Sprint'.
    When querying for a specific session, FastF1 will also accept the
    'Sprint Qualifying'/'SQ' identifier instead of only 'Sprint'/'S' for
    backwards compatibility.

---

### Api Reference Exceptions (`docs/api_reference/exceptions.rst`)

.. _exceptions:

Exceptions
============

Generic Exceptions
------------------

.. autoclass:: fastf1.exceptions.FastF1CriticalError
    :show-inheritance:

.. autoclass:: fastf1.exceptions.RateLimitExceededError
    :show-inheritance:


Data Loading Exceptions
-----------------------

.. autoclass:: fastf1.exceptions.DataNotLoadedError
    :show-inheritance:

.. autoclass:: fastf1.exceptions.FuzzyMatchError
    :show-inheritance:

.. autoclass:: fastf1.exceptions.NoLapDataError
    :show-inheritance:

.. autoclass:: fastf1.exceptions.F1AuthError
    :show-inheritance:


Jolpica-F1 (Ergast) Specific Exceptions
---------------------------------------

.. _jolpica-excpetions:

.. autoclass:: fastf1.exceptions.ErgastError
    :show-inheritance:

.. autoclass:: fastf1.exceptions.ErgastJsonError
    :show-inheritance:

.. autoclass:: fastf1.exceptions.ErgastInvalidRequestError
    :show-inheritance:


Legacy Exceptions (deprecated)
------------------------------

.. autoclass:: fastf1._api.SessionNotAvailableError

.. autoclass:: fastf1.exceptions.InvalidSessionError

---

### Api Reference Index (`docs/api_reference/index.rst`)

*************
API Reference
*************

This page gives an overview of all public FastF1 objects, functions and methods.
All classes and functions exposed in ``fastf1.*`` namespace are public.

The following subpackages are public.

- ``fastf1.core``
- ``fastf1.ergast``
- ``fastf1.events``
- ``fastf1.legacy``
- ``fastf1.livetiming``
- ``fastf1.plotting``
- ``fastf1.utils``


.. toctree::
    :maxdepth: 1
    :caption: Functions

    loading_data
    plotting_data

.. toctree::
    :maxdepth: 1
    :caption: Objects

    events
    session
    timing_data
    telemetry
    results
    circuit_info

.. toctree::
    :maxdepth: 1
    :caption: External APIs

    jolpica
    ergast

.. toctree::
    :maxdepth: 1
    :caption: Advanced

    accounts_auth
    cache_and_rate_limits
    exceptions
    logging
    livetiming
    utils
    deprecated_legacy

---

### Api Reference Jolpica (`docs/api_reference/jolpica.rst`)

.. _jolpica:

.. currentmodule:: fastf1.ergast

Jolpica-F1 API Interface
========================

.. note::

    This API was previously provided by the Ergast motor racing database (Ergast MRD).
    Ergast was shutdown at the beginning of 2025 and
    `Jolpica-F1 <https://github.com/jolpica/jolpica-f1>`__ took over
    as its successor, providing a replacement API that is drop-in compatible.
    While the module names here have not been changed for backwards
    compatibility, all data is now obtained from Jolpica-F1.


Introduction
------------

This module can be used to interface with the
`Jolpica-F1 <https://github.com/jolpica/jolpica-f1>`__ API (previously Ergast).

The :class:`Ergast` object provides access to all Endpoints of the
Jolpica-F1 API.

The `Rate Limits <https://github.com/jolpica/jolpica-f1/blob/main/docs/rate_limits.md>`__
of Jolpica-F1 apply.
FastF1 will handle caching and it will try to enforce rate limits where
possible. For more information on how FastF1 handles caching and rate
limiting see :ref:`rate_limits-caching`.

Result Types
..............

Data can be returned in two different formats:

**Raw Response**

.. autosummary::
   :nosignatures:

   ~interface.ErgastRawResponse

This format is a JSON-like representation of the original JSON data (using
``json.load``).

**Flattened into Pandas DataFrames**

.. autosummary::
   :nosignatures:

   ~interface.ErgastSimpleResponse
   ~interface.ErgastMultiResponse

The complexity of the data that is returned by the API endpoint determines
the exact result type. The return type is documented for each endpoint.

An :class:`~fastf1.ergast.interface.ErgastSimpleResponse` wraps a Pandas
``DataFrame`` directly.

An :class:`~fastf1.ergast.interface.ErgastMultiResponse` consists of a
descriptive ``DataFrame``
(:attr:`~fastf1.ergast.interface.ErgastMultiResponse.description`)
and a list of ``DataFrames`` that contain the main content of the response
(:attr:`~fastf1.ergast.interface.ErgastMultiResponse.content`).


General Options
...............

The following arguments are available as default values on :class:`Ergast` or
individually for each endpoint method:

    - ``result_type`` ('raw' or 'pandas'): Select between RAW responses or
        Pandas DataFrame responses.

    - ``auto_cast`` (`bool`): Select whether all values are automatically
        cast from their default string representation to the most appropriate
        data type.

    - ``limit`` (`int`): Set the limit for the maximum number of results that
        are returned in one request. The server default (30 results) applies
        if this value is not set. The maximum allowed value is 1000 results.


Common Surprises
................

This is a list of things that may be surprising or unexpected for first-time
users.

  - API results are always returned in ascending order. As a result, for
    example, if you query the race schedule without specifying a season, you
    will receive the schedule for the oldest seasons first, starting in 1950.

  - Only some combinations of filter parameters are possible and those vary for
    each API endpoint. FastF1 does not impose restrictions on these
    combinations as the relationships are fairly complex. Instead, an
    :class:`~fastf1.exceptions.ErgastInvalidRequestError` will
    be raised in such a case. The exception will contain the error response
    of the server.


Examples
........

First, import :class:`~fastf1.ergast.Ergast` and create and interface with
all default arguments.

.. doctest::

    >>> from fastf1.ergast import Ergast
    >>> ergast = Ergast()

Simple DataFrame Responses
::::::::::::::::::::::::::

Get information about all circuits that hosted a Grand Prix in 2022.
This is an endpoint that returns an
:class:`~fastf1.ergast.interface.ErgastSimpleResponse`, meaning one single
DataFrame.


.. doctest::

    >>> response_frame = ergast.get_circuits(season=2022)
    >>> response_frame
            circuitId  ...       country
    0     albert_park  ...     Australia
    1        americas  ...           USA
    2         bahrain  ...       Bahrain
    ...
    19     villeneuve  ...        Canada
    20     yas_marina  ...           UAE
    21      zandvoort  ...   Netherlands
    <BLANKLINE>
    [22 rows x 7 columns]

Raw Responses
:::::::::::::

To get the raw data instead of the DataFrame result, specify the return type
as 'raw':

.. doctest::

  >>> ergast.get_circuits(season=2022, result_type='raw')  # doctest: +NORMALIZE_WHITESPACE
  [{'circuitId': 'albert_park',
    'url': 'https://en.wikipedia.org/wiki/Albert_Park_Circuit',
    'circuitName': 'Albert Park Grand Prix Circuit',
    'Location': {'lat': -37.8497,
                 'long': 144.968,
                 'locality': 'Melbourne',
                 'country': 'Australia'}},
  ...]

Note that FastF1's "raw" response is not actually the complete JSON response
that the API provides. Instead, only the actual data part of the response is
returned while metadata (version, query parameters, response length, ...)
are not included.

Renamed Keys and Type Casting
:::::::::::::::::::::::::::::

In the response DataFrame, some keys are renamed from the raw result
so that all column names are unique when flattening more complex responses.
Compare the column names from the result data frame with the raw response above
and note that 'url' has changed to 'circuitUrl' (Responses can include other
URLs as well).

.. doctest::

  >>> response_frame.columns
  Index(['circuitId', 'circuitUrl', 'circuitName', 'lat', 'long', 'locality',
         'country'],
        dtype='object')

Also note, that by default all values will automatically be cast to the most
suitable data type. Ergast itself does provide all values as string, though.
Automatic type casting can be very useful because most of the time it will
make it easier to work with the data. But it is possible to disable automatic
type casting by setting ``auto_cast=False``. For example, by default auto
casting is enabled and *'lat'* and *'long'* will be cast to ``float``,

.. doctest::

  >>> ergast.get_circuits(season=2022, result_type='raw')[0]['Location']
  {'lat': -37.8497, 'long': 144.968, 'locality': 'Melbourne', 'country': 'Australia'}

but with ``auto_cast=False`` both values remain ``str``.

.. doctest::

  >>> ergast.get_circuits(season=2022, result_type='raw', auto_cast=False)[0]['Location']
  {'lat': '-37.8497', 'long': '144.968', 'locality': 'Melbourne', 'country': 'Australia'}

The documentation for each API endpoint includes an "API Mapping" that
shows the structure of the raw response, the updated key names for flattening
and the data types for automatic type casting. Additionally, there is a
"DataFrame Description" that shows which column names will be present in the
result frame. This way it easy to see which keys are renamed.
Additionally, both the "API Mapping" and the "DataFrame Description" will
show the data type to which a value is cast when ``auto_cast=True``.

.. note::
  ``-1`` is used to indicate missing values for ``int``-type values (``int``
  does not support a proper ``NaN`` value)

MultiResponse DataFrames
::::::::::::::::::::::::

There are API endpoints that return complex data structures as a
response. When 'pandas' is selected as result type, these endpoints return a
:class:`~fastf1.ergast.interface.ErgastMultiResponse`. One such endpoint is
the constructor standings endpoint.

.. TODO: the following doctests are skipped because of the broken Ergast API

.. doctest::

  >>> standings = ergast.get_constructor_standings()  # doctest: +SKIP

Called without any 'season' specifier, it returns standings for multiple
seasons. An overview over the returned data is available as a ``.description``
of the response:

.. doctest::

  >>> standings.description  # doctest: +SKIP
     season  round
  0    1958     11
  1    1959      9
  2    1960     10


Note that the API always returns results in an ascending order.
Therefore, when no season is specified, the constructor standings are returned
for the oldest available seasons.

Due to the maximum number of returned results being limited, only data for
three seasons is returned, as can be seen.

The actual standings information is available in separate DataFrames for
each season. These can be accessed as ``.content`` of the response.
The first element in ``.content`` is associated with the first row of the
``.description`` and so on.

.. doctest::

  >>> standings.content[0]  # doctest: +SKIP
     position positionText  ...  constructorName  constructorNationality
  0         1            1  ...          Vanwall                 British
  1         2            2  ...          Ferrari                 Italian
  ...
  7         8            8  ...        Connaught                 British
  8         9            9  ...             OSCA                 Italian
  <BLANKLINE>
  [9 rows x 8 columns]

Pagination
::::::::::

All Ergast response objects inherit from
:class:`~fastf1.ergast.interface.ErgastResponseMixin`. This object provides
support for pagination on all response objects. Ergast uses pagination
to serve results for specific requests on multiple 'pages' when the response
exceeds the limit for the maximum number of results.

For example, when limiting the sesason list to three results, Ergast
responds with:

.. doctest::

  >>> seasons = ergast.get_seasons(limit=3)
  >>> seasons
     season                                          seasonUrl
  0    1950  https://en.wikipedia.org/wiki/1950_Formula_One...
  1    1951  https://en.wikipedia.org/wiki/1951_Formula_One...
  2    1952  https://en.wikipedia.org/wiki/1952_Formula_One...

It is possible to check whether a response contains all results and to obtain
the total number of results:

.. doctest::

  >>> seasons.is_complete
  False
  >>> seasons.total_results # doctest: +SKIP
  74

Now, the builtin pagination can be used to obtain the next result page. The
same limit as before is used.

.. doctest::

  >>> seasons.get_next_result_page()
     season                                          seasonUrl
  0    1953  https://en.wikipedia.org/wiki/1953_Formula_One...
  1    1954  https://en.wikipedia.org/wiki/1954_Formula_One...
  2    1955  https://en.wikipedia.org/wiki/1955_Formula_One...

It is also possible to manually specify an offset into the dataset:

.. doctest::

  >>> ergast.get_seasons(limit=3, offset=6)
     season                                          seasonUrl
  0    1956  https://en.wikipedia.org/wiki/1956_Formula_One...
  1    1957  https://en.wikipedia.org/wiki/1957_Formula_One...
  2    1958  https://en.wikipedia.org/wiki/1958_Formula_One...


API Summary
-----------

Main Interface
..............


.. autosummary::
    :toctree: api_autogen/
    :template: class_summary_noinherited.rst

    Ergast


Response Objects
................

.. autosummary::
    :toctree: api_autogen/
    :template: class_summary_noinherited.rst

    interface.ErgastRawResponse
    interface.ErgastSimpleResponse
    interface.ErgastMultiResponse
    interface.ErgastResultFrame
    interface.ErgastResponseMixin

---

### Api Reference Livetiming (`docs/api_reference/livetiming.rst`)

.. _livetiming:

Live Timing Client
==================

This module can be used to save live timing data during a session.
It is **not** possible to do real-time processing of the data.


.. note::

    Usage of the live timing client requires an active F1TV Access/Pro/Premium subscription.
    FastF1 will direct you to sign in to you F1TV account if you have not already done so.
    You can get more information about the authentication flow in the :ref:`accounts-auth` section.

    Use ``--no-auth`` to connect without signing in, in which case data may be incomplete or
    missing, and ``--auth-method {password,browser}`` to select the sign-in method.

There are two ways to interact with this module.

    - From a python script by creating an instance of
      :class:`.SignalRClient`

    - From the command line by calling ``python -m fastf1.livetiming``


Usage Example
-------------

1. Record live timing data during a session

.. code-block:: console

    python -m fastf1.livetiming save saved_data.txt

or alternatively create a Python script to run the SignalR client

.. code-block:: python

    from fastf1.livetiming.client import SignalRClient

    client = SignalRClient(filename="saved_data.txt")
    client.start()

2. Load this data into FastF1 after the session has finished

.. code-block::

    import fastf1
    from fastf1.livetiming.data import LiveTimingData

    livedata = LiveTimingData('saved_data.txt')
    session = fastf1.get_testing_session(2021, 1, 1)
    session.load(livedata=livedata)

optionally you can load live timing data from two or more files

.. code-block::

    livedata = LiveTimingData('saved_data_1.txt', 'saved_data_2.txt')




Important Notes
---------------

- You should try to record a full session whenever possible. Recording may need
  to start up to one hour before the start of the session to capture all data.
  The api parser may not be able to deal with the data correctly if the
  beginning of a session is missing. Your mileage may vary depending on what
  and how much data is missing.

- You should not mix recorded live timing data and data requested from the api
  after a session. The data will likely not be synchronized correctly.

- You should use the cache with saved live timing data too. This will speed up
  loading of the data considerably after the first run.

- You need to use different cache directories if you want to cache
  saved live timing data and api data **for the same session**!
  The cache cannot tell the data sources apart. If cached data from one source
  already exists it will not be reloaded automatically from a different source.
  See :class:`fastf1.req.Cache` for details on how to configure a custom
  cache directory. One simple way is to add the following line to your code::

    fastf1.Cache.configure(cache_dir='path/to/cache/directory')

- You need to force a cache update if you modify the
  :class:`~fastf1.livetiming.data.LiveTimingData` (e.g. by adding a second
  file). The cache cannot tell that the input source was modified and will
  still use the old cached data.

  You can force-refresh the cache::

    fastf1.Cache.configure(cache_dir='path/to/cache/directory', force_renew=True)

  You only need to use ``forece_renew=True`` once after modifying the
  input data.

- The SignalR Client seems to get disconnected after 2 hours of recording. It
  looks like the connection is terminated by the server. You need to manually
  start a second recording before the first one disconnects if you want to
  have no gap in your recording.

  Use a different output file name for the second (or any subsequent)
  recording. You can then load :class:`.data.LiveTimingData` from multiple
  files. The files need to be provided in chronological order. The content of
  the files may overlap. Data from overlapping recordings is recognized and
  will not be loaded as a duplicate.




Command Line Interface
----------------------

Available commands and options when calling ``python -m fastf1.livetiming``

The module has two main commands

.. code-block:: console

      {save,extract}
        save          Save live timing data
        extract       Extract messages from saved debug-mode data

Save
^^^^

**The main command for recording live timing data during a session**

.. code-block:: console

    usage: python -m fastf1.livetiming save [-h] [--append] [--debug]
           [--timeout TIMEOUT] file

    positional arguments:
      file               Output file name

    optional arguments:
      -h, --help         show this help message and exit
      --append           Append to output file. By default the file is
                         overwritten if it exists already.
      --debug            Enable debug mode: save full SignalR message, not
                         just the data.
      --timeout TIMEOUT  Timeout in seconds after which the client will
                         automatically exit if no data is received


Extract
^^^^^^^

**Only for when data was saved with the optional '--debug' argument**

Recording in debug mode saves the full SignalR messages as received. The non
debug mode saves only the important data part of a message. The data part of
each message needs to be extracted to utilize the debug-mode data.
The extracted data is the same data you get when saving without the '--debug'
argument.

.. code-block:: console

    usage: python -m fastf1.livetiming extract [-h] input output

    positional arguments:
      input       Input file name
      output      Output file name

    optional arguments:
      -h, --help  show this help message and exit


API Summary
-----------

Live Timing Client
^^^^^^^^^^^^^^^^^^

.. currentmodule:: fastf1.livetiming.client

.. autosummary::
    :toctree: api_autogen/
    :template: class_summary_noinherited.rst

    SignalRClient
    messages_from_raw


Live Timing Data Object
^^^^^^^^^^^^^^^^^^^^^^^

.. currentmodule:: fastf1.livetiming.data

.. autosummary::
    :toctree: api_autogen/
    :template: class_summary_noinherited.rst

    LiveTimingData

---

### Api Reference Loading Data (`docs/api_reference/loading_data.rst`)

.. _loading-data:

Loading Data
============

.. currentmodule:: fastf1


Accessing Events and Sessions
-----------------------------

When using FastF1, you usually start by loading an event or a
session. This can be done with one of the following functions.

.. autosummary::
    :toctree: api_autogen/
    :template: function.rst

    get_session
    get_testing_session
    get_event
    get_events_remaining
    get_event_schedule
    get_testing_event

---

### Api Reference Logging (`docs/api_reference/logging.rst`)

.. _logging:

Logging
=======

.. currentmodule:: fastf1


Configure Logging Verbosity
---------------------------

All parts of FastF1 generally log at the log level 'INFO'.
The reason for this is that many data loading processes take multiple
seconds to complete. Logging is used to give progress information here as well
as for showing warnings and non-terminal errors.

The logging level for FastF1 can be easily customized::

    import fastf1

    fastf1.set_log_level('WARNING')

    # ... your code  here ... #

The available levels are (in order of increasing severity): DEBUG, INFO,
WARNING, ERROR and CRITICAL.

.. autofunction:: set_log_level


Advanced Logging API
--------------------

.. _advanced-logging:

This section is usually only relevant for developers and contains information
that is useful for debugging and for implementing logging in FastF1 internal
code.

FastF1 uses loggers for each submodule. All loggers are child loggers of
FastF1's base logger. The log level is usually configured equally for all parts
of FastF1. The :class:`~fastf1.logger.LoggingManager` or the direct access
functions should commonly be used for this.

Note to developers: some parts of FastF1's data loading are wrapped in generic
catch-all error handling to prevent errors in individual data loading tasks to
make FastF1 completely unusable. Instead, unhandled exceptions will be caught,
short error message is logged in level INFO, the full traceback is logged on
level DEBUG and execution will continue as good as possible. This system can
make debugging more difficult because errors are not raised. To circumvent
this, there are two possible ways to disable the catch-all error handling for
data loading:

- explicitly set :attr:`fastf1.logger.LoggingManager.debug` to `True`
- set the environment variable `FASTF1_DEBUG=1`


Logging Manager
...............

.. autoclass:: fastf1.logger.LoggingManager
    :members:


Functions for direct access
...........................

.. automethod:: fastf1.logger.set_log_level
.. automethod:: fastf1.logger.get_logger
.. automethod:: fastf1.logger.soft_exceptions

.. automodule:: fastf1.logger
    :show-inheritance:

---

### Api Reference Plotting Colormaps (`docs/api_reference/plotting_colormaps.rst`)

:orphan:

.. _Team-Colormaps-Overview:

Overview over Team Colormaps
----------------------------

Note that the "official" colors that are shown here may be different from
those that are returned by FastF1 at runtime since they are updated from via
the F1 API for each session and may change during the season.

(Colors in the image below are only displayed accurately, when the
documentation website is viewed in light color mode. Use the switcher in the
top right corner to change between light and dark mode.)


.. plot:: _plots/colormap_overview.py
    :include-source: False

---

### Api Reference Plotting Data (`docs/api_reference/plotting_data.rst`)

.. _plotting-data:


Plotting Data
=============

The ``fastf1.plotting`` submodule contains helper functions for creating data plots.

This submodule mainly offers:
    - team names and colors
    - driver names and driver abbreviations
    - Matplotlib integration and helper functions

FastF1 focuses on plotting with Matplotlib or related libraries like Seaborn.
If you wish to use these libraries, it is highly recommended to enable
extend support for these by calling :func:`~fastf1.plotting.setup_mpl`.


Team Colormaps
--------------

Currently, two team colormaps are supported. Each colormap provides one color
for each team. All functions that return colors for teams or drivers accept an
optional ``colormap`` argument. If this argument is not provided, the default
colormap is used. The default colormap can be changed by using
:func:`~fastf1.plotting.set_default_colormap`.

The ``'fastf1'`` colormap is FastF1's default colormap. These colors are teams'
primary colors or accent colors as they are used by the teams on their website
or in promotional material. The colors are chosen to maximize readability in
plots by creating a stronger contrast while still being associated with the
team. Colors are constant over the course of a season.

The ``'official'`` colormap contains the colors exactly as they are used by
F1 in official graphics and in the TV broadcast. Those colors are often
slightly muted. While that makes them more pleasing to look at in some graphics,
it also reduces the contrast between colors which is often bad for
readability of plots. These colors may change during the season if they are
updated by F1.

See here for a complete list of all colors: :ref:`Team-Colormaps-Overview`


.. note:: **Driver Colors**

    Previously, individual colors for each driver were provided. This is no
    longer the case. The driver color is now equivalent to the team color,
    meaning that drivers from the same team have the exact same color. This
    change was made because different colors for 20 drivers end up looking
    very similar in a lot of cases. Therefore, it is not a good solution to
    use driver specific colors to distinguish between different drivers. Other
    means of plot styling should be used instead.



API Summary
-----------

.. currentmodule:: fastf1.plotting


Configuration and Setup
^^^^^^^^^^^^^^^^^^^^^^^

.. autosummary::
    :toctree: api_autogen/
    :template: function.rst

    setup_mpl


Get Colors, Names and Abbreviations for Drivers or Teams
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. autosummary::
    :toctree: api_autogen/
    :template: function.rst

    get_compound_color
    get_driver_abbreviation
    get_driver_abbreviations_by_team
    get_driver_color
    get_driver_name
    get_driver_names_by_team
    get_driver_style
    get_team_color
    get_team_name
    get_team_name_by_driver


List all Names and Abbreviations for Drivers/Teams in a Session
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. autosummary::
    :toctree: api_autogen/
    :template: function.rst

    get_compound_mapping
    get_driver_color_mapping
    list_compounds
    list_driver_abbreviations
    list_driver_names
    list_team_names


Plot Styling
^^^^^^^^^^^^

.. autosummary::
    :toctree: api_autogen/
    :template: function.rst

    add_sorted_driver_legend
    set_default_colormap


Advanced Functionality
^^^^^^^^^^^^^^^^^^^^^^

.. autosummary::
    :toctree: api_autogen/
    :template: function.rst

    override_team_constants

---

### Api Reference Results (`docs/api_reference/results.rst`)

Results Data
============

.. currentmodule:: fastf1.core

Results data is represented using the following objects. It can be accessed
through the :attr:`Session.results` attribute. To load a session, see :ref:`loading-data`.

.. autosummary::
    :toctree: api_autogen/
    :template: class_summary_noinherited.rst

    SessionResults
    DriverResult

---

### Api Reference Session (`docs/api_reference/session.rst`)

Session
=======

.. currentmodule:: fastf1.core

The :class:`Session` is a core part of FastF1 and serves as a starting point
for accessing various data. A :class:`Session` object represents a specific
race, qualifying, sprint or other Formula 1 session and all data related to
such a session can be accessed through it.

.. autoclass:: Session
   :members:
   :autosummary:

---

### Api Reference Telemetry (`docs/api_reference/telemetry.rst`)

Car Telemetry
=============

.. currentmodule:: fastf1.core

The :class:`Telemetry` object is used to provide car telemetry and position data.


.. autoclass:: Telemetry
   :members:
   :autosummary:

---

### Api Reference Timing Data (`docs/api_reference/timing_data.rst`)

Timing Data
===========

.. currentmodule:: fastf1.core

Timing data is represented using the following objects. It can be accessed
through the :attr:`Session.laps` attribute. To load a session,
see :ref:`loading-data`.

.. autosummary::
    :toctree: api_autogen/
    :template: class_summary_noinherited.rst

    Laps
    Lap



Lap Timing Data
---------------

The following information is available per lap (one DataFrame column
for each):

.. list-table::
   :widths: 20 20 60
   :header-rows: 1

   * - Name
     - Data Type
     - Description
   * - **Time**
     - ``pandas.Timedelta``
     - Session time when the lap time was set (end of lap)
   * - **Driver**
     - ``str``
     - Three letter driver identifier
   * - **DriverNumber**
     - ``str``
     - Driver number
   * - **LapTime**
     - ``pandas.Timedelta``
     - Recorded lap time. To see if a lap time was deleted, check the **Deleted** column.
   * - **LapNumber**
     - ``float``
     - Recorded lap number
   * - **Stint**
     - ``float``
     - Stint number
   * - **PitOutTime**
     - ``pandas.Timedelta``
     - Session time when car exited the pit
   * - **PitInTime**
     - ``pandas.Timedelta``
     - Session time when car entered the pit
   * - **Sector1Time**
     - ``pandas.Timedelta``
     - Sector 1 recorded time
   * - **Sector2Time**
     - ``pandas.Timedelta``
     - Sector 2 recorded time
   * - **Sector3Time**
     - ``pandas.Timedelta``
     - Sector 3 recorded time
   * - **Sector1SessionTime**
     - ``pandas.Timedelta``
     - Session time when the Sector 1 time was set
   * - **Sector2SessionTime**
     - ``pandas.Timedelta``
     - Session time when the Sector 2 time was set
   * - **Sector3SessionTime**
     - ``pandas.Timedelta``
     - Session time when the Sector 3 time was set
   * - **SpeedI1**
     - ``float``
     - Speedtrap sector 1 [km/h] (missing under red flag)
   * - **SpeedI2**
     - ``float``
     - Speedtrap sector 2 [km/h] (missing under red flag)
   * - **SpeedFL**
     - ``float``
     - Speedtrap at finish line [km/h] (missing under red flag and missing on laps where a driver enters the pits)
   * - **SpeedST**
     - ``float``
     - Speedtrap on longest straight or at a select high speed point, dependent on the circuit [km/h] (missing under red flag)
   * - **IsPersonalBest**
     - ``bool``
     - Flag that indicates whether this lap is the official personal best lap of a driver. If any lap of a driver is quicker than their respective personal best lap, this means that the quicker lap is invalid and not counted. For example, this can happen if the track limits were exceeded.
   * - **Compound**
     - ``str``
     - Tyres event specific compound name: SOFT, MEDIUM, HARD, INTERMEDIATE, WET, TEST_UNKNOWN, UNKNOWN. The actual underlying compounds C1 to C5 are not differentiated. TEST_UNKNOWN compounds can appear in the data during pre-season testing and in-season Pirelli tyre tests.
   * - **TyreLife**
     - ``float``
     - Laps driven on this tire (includes laps in other sessions for used sets of tires)
   * - **FreshTyre**
     - ``bool``
     - Tyre had TyreLife=0 at stint start, i.e. was a new tire
   * - **Team**
     - ``str``
     - Team name
   * - **LapStartTime**
     - ``pandas.Timedelta``
     - Session time at the start of the lap
   * - **LapStartDate**
     - ``pandas.Timestamp``
     - Timestamp at the start of the lap
   * - **TrackStatus**
     - ``str``
     - A string that contains track status numbers for all track status that occurred during this lap. The meaning of the track status numbers is explained in :func:`fastf1.api.track_status_data`. For filtering laps by track status, you may want to use :func:`Laps.pick_track_status`.
   * - **Position**
     - ``float``
     - Position of the driver at the end of each lap. This value is NaN for FP1, FP2, FP3, Sprint Shootout, and Qualifying as well as for crash laps.
   * - **Deleted**
     - ``Optional[bool]``
     - Indicates that a lap was deleted by the stewards, for example because of a track limits violation. This data is only available when race control messages are loaded.
   * - **DeletedReason**
     - ``str``
     - Gives the reason for a lap time deletion. This data is only available when race control messages are loaded.
   * - **FastF1Generated**
     - ``bool``
     - Indicates that this lap was added by FastF1. Such a lap will generally have very limited information available and information is partly interpolated or based on reasonable assumptions. Cases were this is used are, for example, when a partial last lap is added for drivers that retired on track.
   * - **IsAccurate**
     - ``bool``
     - Indicates that the lap start and end time are synced correctly with other laps. Do not confuse this with the accuracy of the lap time or sector times. They are always considered to be accurate if they exist! If this value is True, the lap has passed as basic accuracy check for timing data. This does not guarantee accuracy but laps marked as inaccurate need to be handled with caution. They might contain errors which can not be spotted easily. Laps need to satisfy the following criteria to be marked as accurate:

- not an inlap or outlap
- set under green or yellow flag (the api sometimes has issues
  with data from SC/VSC laps)
- is not the first lap after a safety car period
  (issues with SC/VSC might still appear on the first lap
  after it has ended)
- has a value for lap time and all sector times
- the sum of the sector times matches the lap time
  (If this were to ever occur, it would also be logged separately
  as a data integrity error. You usually don't need to worry about
  this.)

---

### Api Reference Utils (`docs/api_reference/utils.rst`)

Utils
=====

.. automodule:: fastf1.utils
    :members:
    :show-inheritance:

---

### Changelog Current (`docs/changelog/current.rst`)

What's new in v3.9.0
--------------------------

(in development)


Behaviour Changes
^^^^^^^^^^^^^^^^^

- Changes to ``Session.results`` for Qualifying and Sprint Qualifying:
    - If a driver was eliminated in Q1 and did not pass the 107% rule, their
      best Q1 time will now be **included** in the result.
    - The "ClassifiedPosition" column will be populated with the drivers'
      respective classified positions. If a driver was eliminated in Q1, the
      value will be set to "N" for "Not Classified".
    - The old behaviour was for the "ClassifiedPosition" column to not be
      used. Drivers who failed the 107% rule had their time excluded from the
      results. The new behaviour follows partially from a change in the data
      that is returned by the Jolpica-F1 API. Further, the new behaviour
      provides more informative data and better matches the behaviour that
      was already described in the documentation.

- Updated internal rate limits for Jolpica-F1 to match changed server
  side limits.


New Features
^^^^^^^^^^^^

- ``SessionResults`` now includes ``Time`` (best lap time) and ``Position``
  for practice sessions ('Practice 1', 'Practice 2', 'Practice 3').
  Previously, both columns were ``NaT``/``NaN`` for these sessions.

- The new method ``Cache.configure`` replaces ``Cache.enable_cache``. All
  arguments are keyword arguments and all of them are optional, so that
  individual cache settings can be changed easily. This also add the option to
  change settings while keeping the default cache location.

- ``Cache.disabled`` and ``Cache.set_disabled`` now accept the keyword
  arguments ``disable_http_cache`` and ``disable_func_cache``. This makes it
  possible to disable the HTTP cache (stage 1) and the parsed-data cache
  (stage 2) separately. By default, both are disabled, as before.


Deprecations
^^^^^^^^^^^^

- ``fastf1.utils.recursive_dict_get``, ``fastf1.utils.to_datetime`` and
  ``fastf1.utils.to_timedelta`` are deprecated. They were never intended to
  be part of the public API. The implementations have been moved to the
  internal ``fastf1.internals.parsing_helpers`` module. The public names
  continue to work and forward to the internal implementations, but emit a
  ``DeprecationWarning``
  and will be removed in a future release (#884).

- The ``round`` keyword argument of ``EventSchedule.get_event_by_round`` is
  deprecated and will be removed in a future version. Use ``round_number``
  instead. (#890)

- ``Cache.enable_cache`` is deprecated and will be removed in a future
  version. Use ``Cache.configure`` instead.

- ``Cache.ci_mode`` is deprecated and will be removed in a future version. Use
  ``Cache.offline_mode`` instead.


Removals
^^^^^^^^

- The deprecated function ``fastf1.utils.delta_time`` has been removed. It
  was deprecated in v3.0.0 because it produced inaccurate results (#884).


Increased minimum versions for dependencies
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- The minimum supported version of ``requests-cache`` is now 1.3.0.



What's new in v3.8.3
--------------------

(released 29/04/2026)


Bug Fixes
^^^^^^^^^

- Fixed a bug that caused a non-existent first lap to be added for some drivers that did not start a race. This
  was observed in the 2026 Chinese Grand Prix. (#899)

- Fixed an issue that lead to missing tyre data for some laps when the source tyre data was delayed at the start
  of a session. This was for example observed in the 2018 Azerbaijan Grand Prix. (#893)

- Fixed an issue where unexpected driver data from a support race altered the F1 driver data.
  (#908) (by @Casper-Guo)


What's new in v3.8.2
--------------------

(released 29/03/2026)


Bug Fixes
^^^^^^^^^

- Fixed a bug that caused crash laps to be duplicated when telemetry data was loaded separately after laps
  data had already been loaded (#852) (by @sheehanr).

- Cleanly handle empty timestamps in responses from the Jolpica-F1 API (#868).


What's new in v3.8.1
--------------------

(released 11/02/2026)


Bug Fixes
^^^^^^^^^

- Patches to support 2026 Pre-Season Testing



What's new in v3.8.0
--------------------

(released 10/02/2026)


Dependency Changes
^^^^^^^^^^^^^^^^^^

- Support for Python 3.9 is dropped. Python 3.10 is the new minimum version.

- Pydantic is added as a new dependency.

- The minimum required versions for selected dependencies are increased as follows:

  - matplotlib>=3.8.0
  - numpy>=1.26.0
  - pandas>=2.1.1
  - requests>=2.30.0
  - scipy>=1.11.0


New Features
^^^^^^^^^^^^

- Missing speed trap values are now filled in by FastF1 when possible (#834).

- A new submodule ``fastf1.exceptions`` is introduced. This submodule contains all public
  custom exceptions going forward. Importing exceptions from other parts of FastF1 is deprecated.

- FastF1 is now able to auto-generate (with limitations) team name and color constants that are
  required for full functionality of the ``fastf1.plotting`` submodule. This is done based on
  data from the F1 API. It serves as a fallback in case of team (name) changes or when plotting
  data of a future season where FastF1 has no built-in constants (yet).
  Note that auto-generated team name constants may be imperfect. When auto-generated,
  all color schemes will follow the 'official' color scheme. (#848)

- Preliminary team name and color constants for 2026 have been added. Further changes may be
  made at the beginning of the season to better capture the teams identities and branding and
  to make the color palette more distinguishable. (#848)


Bug Fixes
^^^^^^^^^

- Prevent support race drivers from being included in the driver list and result data. This
  previously occurred in some edge cases due to bad source data. (#836)

- ``RateLimitExceededError`` is now raised as intended an no longer captured and hidden by
  internal error handling (#748, #842).


Deprecations
^^^^^^^^^^^^

- Importing ``ErgastError``, ``ErgastJsonError`` and ``ErgastInvalidRequestError`` from
  ``fastf1.ergast.interface`` is deprecate. Import from ``fastf1.exceptions`` instead.

- Importing ``NoLapDataError``, ``DataNotLoadedError`` and ``InvalidSessionError`` from
  ``fastf1.core`` is deprecate. Import from ``fastf1.exceptions`` instead.

- Importing ``RateLimitExceededError`` from ``fastf1`` is deprecated. Import from
  ``fastf1.exceptions`` instead.


Note: Deprecated API is removed two minor releases after its deprecation.

---

### Changelog Index (`docs/changelog/index.rst`)

Release Notes
=============

Looking for :ref:`previous-release-notes`?

.. include:: current.rst

---

### Changelog Previous (`docs/changelog/previous.rst`)

:orphan:

.. _previous-release-notes:

Release Notes for Older Versions
================================

.. toctree::
  :maxdepth: 1

  v3.7.x
  v3.6.x
  v3.5.x
  v3.4.x
  v3.3.x
  v3.2.x
  v3.1.x
  v3.0.x
  v2.3.2
  v2.3.1
  v2.3.0

  v2.2.9
  v2.2.8
  v2.2.7
  v2.2.6
  v2.2.5
  v2.2.4
  v2.2.3
  v2.2.2
  v2.2.1
  v2.2.0

  v2.1.13
  v2.1.12
  v2.1.11
  v2.1.10
  v2.1.9
  v2.1.8
  v2.1.7
  v2.1.6
  v2.1.5
  v2.1.4
  v2.1.3
  v2.1.2
  v2.1.1
  v2.1.0

  v2.0.2
  v2.0.1
  v2.0.0
  v1.5.1

---

### Changelog V2.0.0 (`docs/changelog/v2.0.0.rst`)

v2.0.0
------

first release of this fork

- Changes:

  - fixed a bug where pandas.DataFrame functionality did not properly work with
    the `Laps class`

  - additional fixes for some minor bugs in `core.get_session`

- New:

  - `track`: module for track and track position related stuff

  - `experimental.syncsolver`: an attempt at better data synchronization

---

### Changelog V2.0.1 (`docs/changelog/v2.0.1.rst`)

v2.0.1
------

Integration of a newer version of Ax6's old repository

This integrates a more recent version of the old repository.
See Issue #1

- Possibly breaking changes
  - :mod:`fastf1.plotting`: access to team colors changed

    use new function :func:`fastf1.plotting.team_color`

  - :mod:`fastf1.core.Laps`: :func:`pick_driver_number` and :func:`pick_driver_numbers` have been removed.

    :func:`fastf1.core.Laps.pick_driver` and :func:`fastf1.core.Laps.pick_drivers` do now accept driver numbers a drivers'
    three letter identifiers. Number and letter identifiers can be mixed in a single function call.

- Changes:

  - An error that previously resulted in the loading of laps failing completely is now handled slightly better.
    Data loading will now only fail for a driver which is actually concerned by this error and not for all drivers.

    See: https://github.com/theOehrly/Fast-F1/issues/1#issuecomment-670712178
    This still needs to be fixed properly at some point.

  - Fix crash if cache dir does not exist

  - Some under the hood cleanups and improvements

  - Somewhat improved documentation

- New:

  - :func:`fastf1.utils.delta_time` for comparing lost/gained time between two drivers

  - manual patch file for Bottas in testing

---

### Changelog V2.0.2 (`docs/changelog/v2.0.2.rst`)

v2.0.2: API code overhaul
==========================
This version integrates a major overhaul of the api code (:mod:`fastf1.api`)

- Possibly breaking changes:

  - Renamed dataframe column 'LastLapTime' to 'LapTime' for the dataframe returned by :func:`api.timing_data`
    First, this makes more sense.
    Second, this column is currently already renamed to 'LapTime' later and already accessible under this name
    in the dataframe returned by :func:`core.Session.load_laps`. Therefore the renaming makes the column name
    be consistent between api and core.

    (This also applies to the dictionary returned by the private function :func:`api._laps_data_driver`),

  - Data types in dataframes may have changed

  - Some private functions (prefixed by '_') may have a different name, parameters and return value now

- Changes:
  - rewrote large parts of :mod:`fastf1.api` with a somewhat cleaner implementation

    - more stability

    - better/more correct PitIn/PitOut and general lap data in some sessions (was missing last lap sometimes but had
      a first lap that didn't actually exist

    - api.timing_data and thereby also session.load_laps will raise api.SessionNotAvailableError
      if the api request returned no data. This usually happens if the session never took place because it was cancelled.

    - Attempted to fix a bug where timing data from two sources can not be merged. This is caused by the received API
      data going backwards in time by one lap. This causes data to be added to the wrong lap.
      This problem was the reason for having patch files for some drivers/sessions. The patch files have now been
      removed as they are no longer necessary.

    - improved documentation a bit

  - light cleanup and light documentation improvements of :mod:`fastf1.core`

  - suppressed python-levenshtein warning; it is really not necessary to have it installed for this module

  - changed logging format for hopefully better readability

  - tried to fix lap time axis again; hopefully this time I got it right

---

### Changelog V2.1.0 (`docs/changelog/v2.1.0.rst`)

v2.1.0: Refactoring, accuracy improvements and a more accessible interface
==========================================================================

- Possibly breaking changes:

  - The 'Space' column has been renamed to 'Distance' as this makes more sense

  - :func:`fastf1.utils.delta_time` now returns two values; see explanation in the documentation

  - Lap telemetry is no longer precalculated and no longer saved in a separate column of the :class:`Laps` DataFrame.
    This telemetry is now a computed property of :class:`Laps` and :class:`Lap`

    - calculated property `.telemetry`: This contains position and car data merged into one instance of
      :class:`Telemetry` (instance of `DataFrame`). The data is comparable to the previous 'telemetry' column.
      This data is intended for easy plotting. It should not be used for any further calculations as it
      contains interpolated values.

      .. code-block::

        laps = session.load_laps()
        fastest = laps.pick_fastest()

        tel = fastest['telemetry']  # will now fail as telemetry is no longer saved in DataFrame/Series
        tel = fastest.telemetry  # will (still) work as this now accesses the computed property

    - function `get_car_data`, `get_pos_data`: These functions are available for :class:`Lap` and :class:`Laps`.
      They return the telemetry data as received from the api with minimal postprocessing and crucially
      unmerged and without any interpolated values. This data should be used if you intend to do any further
      calculations with it.

      Also read the new documentation section about doing accurate calculations: :ref:`howto_accurate_calculations`

  - Patches and color scheme changes which were automatically applied when importing :mod:`fastf1.plotting`
    now need to be enabled explicitly. This is done by calling :func:`fasf1.plotting.setup_mpl`.
    This function offers configuration through keyword arguments. The defaults are equal to what was done
    automatically before.
    It is highly recommended that you call this function to set up your matplotlib plotting environment.

  - The formatting of timedelta values in matplotlib plots is now handled by an external module called 'Timple'.
    As part of this change, the function :func:`fastf1.plotting.laptime_axis` has been removed. Timedelta data
    is now detected automatically if matplotlib timedelta support is enabled through :func:`fastf1.plotting.setup_mpl`.
    This will hopefully make the plotting of timedelta values considerably more reliable.

  - The computed telemetry channels 'Distance' (before: 'Space'), 'DriverAhead' and 'DistanceToDriverAhead' are no
    longer added to the telemetry data by default. This is done for speed and accuracy reasons. These channels can now
    be added by calling the appropriate :meth:`Telemetry.add_*` methods of the new :class:`fastf1.core.Telemetry` class.

  - The cache has been completely rewritten. It is now fully supported again and can detect version updates which
    require updating the cached data.
    Enabling the cache is now done using :func:`fastf1.api.Cache.enable_cache`



- Changes:
  - Accuracy improvement: Changes to some parts of the general flow of processing data to reduce calculation errors

  - Accuracy improvement: slightly better determination of the time at which a lap starts

  - Speed improvement: Faster parsing of API data

  - Added track status information to laps data

  - Added lap accuracy validation as a boolean 'IsAccurate' value for each lap. This is set based on track status,
    availability of some required lap data, pit stops

  - Added 'Source' to telemetry data to indicate whether a value is original ('car' or 'pos' depending on source)
    or interpolated

  - Added the class :class:`fastf1.core.Lap` which subclasses :class:`pd.Series`. :class:`Lap` is now the result of
    slicing :class:`fastf1.core.Laps`.

  - Added additional `pick_*()` functions to :class:`fastf1.core.Laps`

  - Added :class:`fastf1.core.Telemetry` which subclasses :class:`pd.DataFrame`. This class offers various methods
    for working with the telemetry data and should make it easier to work with the data. Previously inaccessible
    functionality is now accessible in a more DataFrame-like style.

  - Added various slicing capabilities for :class:`fastf1.core.Telemetry`

  - Telemetry data can be sliced at any point and calculated telemetry channels (Distance, Driver Ahead, ...)
    can be added to this slice specifically.

    Example usages:

      - 'Distance' can be calculated continuously over multiple laps (starts at zero on the first lap
        and increases all the time).

      - 'DriverAhead' can now be calculated for small telemetry slices more efficiently

  - DistanceToDriverAhead is reimplemented and returns a considerably smoother result now. This is at the cost of
    increasing integration error when used over longer periods of time (i.e. over multiple laps). To work around this,
    it should be applied to laps individually. Additionally, the old implementation is still available in
    :mod:`fastf1.legacy`.

  - Add a SignalR client for receiving and saving live timing and telemetry data during a session.


- Fixed:
  - fix: SessionNotAvailableError is now raised as Exception instead of BaseException

  - fix a crash when there is no valid car telemetry data at all (2019, Australia, FP3)

  - fix a crash caused by the resampling progressbar when there are very few laps in a session (2019, Azerbaijan, FP1)

  - fix a crash in _inject_position when some telemetry data is missing (2019, Silverstone, FP1)

  - fix a crash when data for a session can be requested but the data does not contain any useful values at
    all (2020, Styria, 'FP3')

---

### Changelog V2.1.1 (`docs/changelog/v2.1.1.rst`)

v2.1.1
------

 Add support for recording and using live timing data

- Possibly breaking changes:

  - :meth:`fastf1.Session.load_laps`: Data will now be loaded without
    telemetry by default, i.e. only timing data is loaded.
    Telemetry data is usually not available anyways, therefore this prevents
    a confusing error.

- Changes:

  - Possibility to record live timing data
  - Possibility to use recorded live timing data as a data source

---

### Changelog V2.1.10 (`docs/changelog/v2.1.10.rst`)

v2.1.10
-------

 Ergast compatibility

- introduce a custom user agent to identify FastF1 when requesting data from the Ergast API

---

### Changelog V2.1.11 (`docs/changelog/v2.1.11.rst`)

v2.1.11
-------

- Fix: last inlap missing from ``Laps``
- Add schedule patch for Sprint Race Weekend at Brazil GP

---

### Changelog V2.1.12 (`docs/changelog/v2.1.12.rst`)

v2.1.12
-------

- fix: crash in lap data parser if a driver did not do any proper laps in a
  session
- fix: crash in :func:`fastf1.core.Telemetry.calculate_driver_ahead` if a
  driver did not participate in the session (by @bambz96)
- enable automatic cache expiration for requests-cache (#57)
- fix: requests cache not cleared if `force_renew=True` is used with
  :func:`fastf1.api.Cache.enable_cache`

---

### Changelog V2.1.13 (`docs/changelog/v2.1.13.rst`)

v2.1.13
-------

- fixed issue #74: don't assume that a further session status change
  (e.g. ended, finalized) exists after the last lap
- improved error handling if there exists no usable lap data for any
  driver (#73, e.g. Imola 2021 FP1)
- :func:`fastf1.core.get_session` should not quietly return
  :class:`fastf1.core.Weekend` instead of :class:`fastf1.core.Session`
  if an invalid event name is given.

---

### Changelog V2.1.2 (`docs/changelog/v2.1.2.rst`)

v2.1.2
------

Hotfixes for loading live timing data

- Fix failure to load live timing data due to an error in the
  api cache function wrapper.

- Improve track status loading

---

### Changelog V2.1.3 (`docs/changelog/v2.1.3.rst`)

v2.1.3
------

Improved error handling

Added error handling for partially invalid data when loading car data
and position data.

---

### Changelog V2.1.4 (`docs/changelog/v2.1.4.rst`)

v2.1.4
------

Bug fixes and various minor improvements

- Fix a bug introduced in v2.1.3 which prevented the loading of
  any data from the api

- Make the api parser more robust and tolerant against invalid data

- various small improvements

---

### Changelog V2.1.5 (`docs/changelog/v2.1.5.rst`)

v2.1.5
------

Improved robustness and minor fixes

- Make the data parsing in :class:`fastf1.livetiming.data.LiveTimingData` more
  robust and tolerant against unexpected data.

- some more small improvements regarding logging and other stuff

---

### Changelog V2.1.6 (`docs/changelog/v2.1.6.rst`)

v2.1.6
------

 Added weather data, general improvements and bug fixes

- Add weather data (#26)
  See: :meth:`.core.Lap.get_weather_data`, :meth:`.core.Laps.get_weather_data`,
  :attr:`.core.Session.weather_data`
- Fix: error when calling :meth:`.core.Laps.get_pos_data` (#22)
- Fix: error when calling `get_telemetry` on the first lap (or a set of laps
  containing the first lap)
- Make the live timing client exit more cleanly

---

### Changelog V2.1.7 (`docs/changelog/v2.1.7.rst`)

v2.1.7
------

- fix crash when loading cached data after dependencies have been updated
- specify minimum versions for pandas and numpy
- fix incorrect Alpine team name
- fix future warnings and deprecation warnings caused by Pandas 1.3.0

---

### Changelog V2.1.8 (`docs/changelog/v2.1.8.rst`)

v2.1.8
------

 Add temporary support for sprint qualifying

- This release adds a temporary patch to support weekends with sprint
  sprint qualifying and their changed order of sessions.
  To get data for sprint qualifying, you can use the ``fastf1.get_session``
  function with the argument ``event='SQ'``.
  Also remember that FP2 is on a Saturday on these weekends. FP3 does
  not exist.

---

### Changelog V2.1.9 (`docs/changelog/v2.1.9.rst`)

v2.1.9
------

- switch renamed dependency 'fuzzywuzzy' to new name 'thefuzz'
- add support for getting team colors from incomplete or partial team
  names or from team names containing typos or extra words
- make fuzzy string matching for event names case-insensitive
- set missing lap start times to pit out time where possible (fixes issue #29),
- add new api function :func:`fastf1.api.driver_info`
- support incomplete laps (not timed) caused by drivers crashing/retiring
  during a lap: infer as much information as possible so that telemetry
  can be accessed easily (fixes issues #36 and #41)

---

### Changelog V2.2.0 (`docs/changelog/v2.2.0.rst`)

v2.2.0
------

This release introduces a range of new features, bug fixes and improvements.
While backwards compatibility has been kept in mind, some breaking changes
are required.


Changes and New Features:

  - New :class:`fastf1.events.EventSchedule`: The event schedule provides
    information about session start times, event format, name and location of
    upcoming events as well as previous event. The schedule data for the
    current season is pulled from an external source that is updated regularly.
    This should solve issues caused by schedule changes during the seasons
    or even during a race weekend.

  - New :class:`fastf1.events.Event`: This object represents a single event
    and holds the same information as the event schedule, but for individual
    events.

  - New methods :meth:`fastf1.get_testing_session`,
    :meth:`fastf1.get_event`, :meth:`fastf1.get_testing_event` and
    :meth:`fastf1.get_event_schedule`

  - The cache now implements better automatic cache control and is used for
    all requests throughout FastF1.

  - The combination of improved caching and the implementation of the new
    event schedule now allow fastf1 to be used even if the Ergast API is not
    accessible. This improves reliability in case of temporary server or
    network problems.

  - Full offline support: Scripts can be run offline if they have been run
    at least once with an active internet connection and caching enabled.

  - Introduces the new objects :class:`fastf1.core.SessionResults` and
    :class:`fastf1.core.DriverResult`. These classes are built on top of
    :class:`pandas.DataFrame` and :class:`pandas.Series`. They provide
    information about all drivers that participated in a session.
    This information includes driver numbers, names, team names, finishing
    results, ...
    Session results are available for all sessions supported by the
    Ergast database.

  - A hard coded list of drivers is no longer required for testing sessions.
    This data can now be pulled from the api as well.

  - A more understandable error will be raised if properties of the
    :class:`~fastf1.core.Session` object are accessed which are not yet
    available because the relevant data has not been loaded.


Bug Fixes:

  - Fixed a bug that caused rain fall to always be true in weather data (#76)


Breaking Changes:

  - For **testing events**, :class:`fastf1.core.Session` objects can no longer be
    created through :func:`fastf1.get_session`. You need to use
    :func:`fastf1.get_testing_session` instead.

  - :attr:`fastf1.core.Session.date` is now a :class:`pandas.Timestamp`
    instead of a string.

  - The signature ``fastf1.core.Session.__init__(weekend, session_name)``
    has been changed to
    ``fastf1.core.Session.__init__(event, session_name)`` to adhere to
    new naming conventions. This is a breaking change if the arguments are
    given as keyword arguments.

  - :func:`fastf1.get_session` may return a different session now for some
    edge cases, if you load sessions by name instead of by round number.

  - The property :attr:`fastf1.core.Session.results` is now an instance of
    :class:`fastf1.core.SessionResults` instead of :class:`dict`. Most of the
    previously available data is accessible through the new data replacement
    object. Some special information like GPS coordinates and altitude are no
    longer available though. If you think that this data should still be
    provided by FastF1 in the future, please open an issue for that.

  - The datatype of the telemetry 'Brake' data channel is changed from
    ``int`` to ``bool``, as brake data was never actually more accurate
    than this. The representation as integer (percentage) values was
    misleading.


Deprecations:

  (Objects, methods and attributes deprecated in v2.2 will be removed
  in v2.3. Until then, accessing them will still work but a FutureWarning
  is shown, reminding you of the deprecation.)
  **Removal has been delayed for user convenience and because
  there exist no problems currently which make a removal immediately necessary.
  The new removal target is v3.0.0**


  - :class:`fastf1.core.Weekend` has been replaced with
    :class:`fastf1.events.Event`. All previously available methods and
    properties are implemented by the replacement object, although they have
    been partially deprecated.

  - The attributes ``name``, ``date`` and ``gp`` of
    :class:`fastf1.core.Weekend` have been deprecated.
    The replacement object :class:`fastf1.events.Event` subclasses
    :class:`pandas.Series`. The standard ways for accessing pandas Series'
    values should be used. The attributes have been additionally renamed in
    their Series representation.
    For example:

      - ``Weekend.name`` --> ``Event.EventName`` or ``Event['EventName']``
      - ``Weekend.date`` --> ``Event.EventDate`` or ``Event['EventDate']``
      - ``Weekend.gp`` --> ``Event.RoundNumber`` or ``Event['RoundNumber']``

  - The attribute :attr:`fastf1.core.Session.weekend` has been replaced by
    :attr:`fastf1.core.Session.event` to adhere to new naming conventions.

  - The function :func:`fastf1.core.get_round` has been deprecated and will be
    removed without replacement in v2.3. Use :func:`fastf1.get_event`
    instead and and get the round number from the returned event object.

  - :func:`fastf1.core.Session.load_laps` has been deprecated. Use
    :func:`fastf1.core.Session.load` instead, which offers more flexibility
    for deciding which data should be loaded. The new method will no longer
    return a :class:`~fastf1.core.Laps` object! You should access the
    :class:`~fastf1.core.Laps` object through
    :attr:`fastf1.core.Session.laps`

  - :class:`fastf1.core.Driver` has been replace with
    :class:`fastf1.core.DriverResult` which has a different signature.

  - The attributes ``grid``, ``position``, ``name``, ``familyname`` and
    ``team`` of :class:`fastf1.core.Driver` have been deprecated.
    The replacement object :class:`fastf1.core.DriverResult` subclasses
    :class:`pandas.Series`. The standard ways for accessing pandas Series'
    values should be used. The attributes have been additionally renamed in
    their Series representation.
    For example:

      - ``Driver.name`` --> ``DriverResult.FirstName`` or
        ``DriverResult['FirstName']``
      - ``Driver.familyname`` --> ``DriverResult.LastName`` or
        ``DriverResult['LastName']``
      - ``Driver.team`` --> ``DriverResult.TeamName`` or
        ``DriverResult['TeamName']``
      - ``Driver.grid`` --> ``DriverResult.GridPosition`` or
        ``DriverResult['GridPosition']``
      - ``Driver.position`` --> ``DriverResult.Position`` or
        ``DriverResult['Position']``

---

### Changelog V2.2.1 (`docs/changelog/v2.2.1.rst`)

v2.2.1
------

Changes:

  - Log ergast error tracebacks on level DEBUG instead of WARNING to avoid
    confusion when a failure was to be expected.

Bug Fixes:

  - Fixed: no session results for Verstappen (driver number 1 vs 33)
    (by @vlesierse)
  - Fixed: slicing telemetry by using multiple laps as a reference returns no
    data if some laps have NaT values for 'Time' or 'LapStartTime'
  - Fixed regression: Loading of livetiming no longer possible since v2.2.0 if
    recording does not contain a driver list

---

### Changelog V2.2.2 (`docs/changelog/v2.2.2.rst`)

v2.2.2
------

Changes:

  - Implement support for reading information about a drivers personal best
    lap from the api. :func:`~fastf1.core.Laps.pick_fastest` will now by
    default return the quickest lap that is also marked as personal best lap
    of any driver. This fixes the long standing problem that the fastest lap
    returned by this function may actually be a deleted lap.


Bug Fixes:

  - Fixed: data for the 2022 Saudi Arabian Grand Prix can not be loaded (#135)
  - Fixed: incorrect python version check in live timing client, that
    prevented running on actually supported versions of python (#132)

---

### Changelog V2.2.3 (`docs/changelog/v2.2.3.rst`)

v2.2.3
------

Bug Fixes:

  - Fixed crash in :func:`fastf1.Telemetry.calculate_driver_ahead` in case
    of missing car data (#146)

---

### Changelog V2.2.4 (`docs/changelog/v2.2.4.rst`)

v2.2.4
------

Bug Fixes:

  - compatibility fixes for supporting 'Sprint' sessions for the 2022 season
    (see also #160)

---

### Changelog V2.2.5 (`docs/changelog/v2.2.5.rst`)

v2.2.5
------

Bug Fixes:

  - Fixed grid position, position and points missing from Sprint sessions
    result in 2022 (#166)


New Features:

  - Added :func:`fastf1.plotting.driver_color` to get driver colors which are
    similar to the team color but slightly different between both drivers of
    one team. This ways the drivers can be differentiated better.
    (by @dialtone in #159)

  - Added support for loading race control messages, see
    :attr:`fastf1.core.Session.race_control_messages`
    (by @bruzie in #163)

---

### Changelog V2.2.6 (`docs/changelog/v2.2.6.rst`)

v2.2.6
------

Bug Fixes:

  - Fixed incorrect lap start times for first lap after a red flag restart

  - Fixed first lap missing if a driver crashed during the first lap of a
    sprint race (#175)

  - Fixed headshot url missing from result of :func:`fastf1.api.driver_info`
    (by @bruzie in #173)

New Features:

  - Added a check detect and to remove incorrect lap times in the api parser
    (#167)

---

### Changelog V2.2.7 (`docs/changelog/v2.2.7.rst`)

v2.2.7
------

Bug Fixes:

    - Fixed an issue that prevented merging of car data and position data
      in some cases (see #180)

---

### Changelog V2.2.8 (`docs/changelog/v2.2.8.rst`)

v2.2.8
------

Bug Fixes:

  - Ensure that :attr:`fastf1.core.Session.drivers` returns a list of
    unique values. This prevents problems that result from drivers being
    incorrectly listed multiple times in the session result information.
    (see #182 for example)

---

### Changelog V2.2.9 (`docs/changelog/v2.2.9.rst`)

v2.2.9
------

Bug Fixes:

    - Fix a typo in :attr:`fastf1.plotting.DRIVER_TRANSLATE` (#207)

---

### Changelog V2.3.0 (`docs/changelog/v2.3.0.rst`)

v2.3.0
------

Bug Fixes:

  - The matplotlib dependency version is now required to be >= 3.3.3 to prevent
    incompatibility. (#210)

  - Fixed: NaT values for 'Time' or 'LapStartTime' may cause a crash
    in :func:`fastf1.core.Telemetry.calculate_driver_ahead` (#151)

  - Fixed: Data for speed trap 'SpeedST' is added to the wrong lap.
    This additionally caused empty laps to exist for some drivers at the
    beginning of some sessions.

  - Fixed: :func:`fastf1.core.Telemetry.add_driver_ahead` could not
    be called on previously resampled telemetry data. (#178)

  - Added: Better error handling for sessions that did not take place.

  - Fixed: Tyre compound shown for some laps was incorrect in some special
    cases. (#204)

  - Fixed: Incorrect first and last name for Hulkenberg in fallback driver list
    (by @niallmcevoy)

  - Fixed: metadata for :class:`~fastf1.core.Telemetry` was not propagated
    correctly in :func:`fastf1.core.Telemetry.merge_channels` and
    :func:`fastf1.core.Telemetry.resample_channels`.

  - Fixed: incorrect call of scipy method in
    :func:`fastf1.legacy.inject_driver_ahead`

  - Fixed: Error handling regression in :func:`fastf1.core.Session.load`

  - Fixed: :exc:`~fastf1.core.DataNotLoadedError` not raised for `car_data` and
    `pos_data`.


New Features:

  - Added: Function :func:`fastf1.get_events_remaining` (by @oscr)

  - Added: Support for shorthand paths (e.g. '~/cache') in
    :func:`fastf1.Cache.enable_cache` (by @oscr)


Changes:

  - The default base url scheme for Ergast is changed from http to https.


Deprecations and Notices for Upcoming Changes:

  - Deprecation: Undocumented function :func:`fastf1.ergast.fetch_weekend`
    will be removed without a direct replacement in a future version
    (target: v3.0.0).

  - Change: :func:`fastf1.utils.to_timedelta` and
    :func:`fastf1.utils.to_datetime` will return `NaT` instead of raising and
    exception if a valued cannot be parsed in a future version
    (target: v3.0.0).

---

### Changelog V2.3.1 (`docs/changelog/v2.3.1.rst`)

v2.3.1
------

Maintenance release for updating driver names and colors for the 2023 season
(#326 by @Casper-Guo).

---

### Changelog V2.3.2 (`docs/changelog/v2.3.2.rst`)

v2.3.2
------

Maintenance release to limit the version of pandas to <2.0.0.

---

### Changelog V3.0.X (`docs/changelog/v3.0.x.rst`)

What's new in v3.0.7
--------------------

(released 17/07/2023)

Bug Fixes and Improvements
^^^^^^^^^^^^^^^^^^^^^^^^^^

- Fixed an issue that prevented telemetry data from being loaded when position
  data is missing (and vice versa) (#412)

- Fixed loading of Sprint Shootout results
  (#413, regression introduced in v3.0.3)

- Added driver color for Ricciardo at AlphaTauri (by @pesaventofilippo in #418)


What's new in v3.0.6
--------------------

(released 21/06/2023)

Release forces a cache update after updating from v3.0.4 and lower. Else, the
changes from v3.0.5 are not applied if the data is cached already.


What's new in v3.0.5
--------------------

(released 21/06/2023)

Bug Fixes and Improvements
^^^^^^^^^^^^^^^^^^^^^^^^^^

- Fixed an error when loading historic sessions (#400).

- Fixed an error where lap times are incorrectly not marked as 'Personal Best'.
  This also caused :meth:`~fastf1.core.Laps.pick_fastest` to return incorrect
  laps. (#403)



What's new in v3.0.4
--------------------

(released 03/06/2023)

Bug Fixes and Improvements
^^^^^^^^^^^^^^^^^^^^^^^^^^

- Added missing color for compound "TEST-UNKNOWN" (by @Casper-Guo)

- Bumped minimum version requirement for dependency 'timple'



What's new in v3.0.3
--------------------

(released 19/05/2023)

Bug Fixes and Improvements
^^^^^^^^^^^^^^^^^^^^^^^^^^

- Fixed incorrectly formatted color codes for tyre compound colors.
  (by @Casper-Guo)

- Fixed a bug that prevented the calculation of results for Qualifying-like
  sessions (for example Sprint Shootout) that only occurred on Pandas v1.5.3
  and older.



What's new in v3.0.2
--------------------

(released 09/05/2023)

Bug Fixes and Improvements
^^^^^^^^^^^^^^^^^^^^^^^^^^

- Improved support for Sprint Shootout sessions and added session results for
  these. (by @mdsakalu)

- Improved exception handling on various internal functions



What's new in v3.0.1
--------------------

(released 07/05/2023)

Bug Fixes
^^^^^^^^^

- fixed a bug that prevented the use of the livetiming client from the
  commandline



What's new in v3.0.0
--------------------

(released 02/05/2023)

New Features
^^^^^^^^^^^^

- Caching is now enabled by default and does not need to be manually configured
  anymore. The cache defaults to using operating system specific default
  locations that are intended for storing temporary files.
  The cache directory can either be changed from within a script or by setting
  and environment variable to define an alternative cache location.
  See: :class:`fastf1.Cache`
  (by @oscr)

- Full support for the Ergast F1 API has now been added, replacing the very
  limited functionality that was previously available. Features of the new
  implementation:

  - all endpoints supported
  - all query filters supported
  - can return data as Pandas DataFrames or raw
  - can do automatic type casting to the best suited data type
  - uses caching
  - supports result limits and pagination
  - enforces rate limits defined by Ergast (with cached requests not counting
    towards the rate limits)

  See: :ref:`jolpica`

- The livetiming client now supports all current versions of Python. The limit
  to version 3.9 and lower no longer exists for this feature. A big thank you
  to @oscr for integrating the problematic python-signalr-client dependency
  into FastF1 and fixing the problems that existed with Python 3.10 and higher.

- The log level for all parts of FastF1 can now be easily configured using
  :func:`fastf1.set_log_level`. The logging system in FastF1 has been
  reimplemented to make debugging easier. See :ref:`logging`

- A partial last lap will now be added to :class:`fastf1.core.Laps` when a
  driver retires on track. This especially will make it easier to plot
  telemetry data of such a lap as there is now a corresponding
  :class:`fastf1.core.Lap`.

- When loaded, race control messages will now be parsed to find which laps
  were deleted. The :class:`fastf1.core.Laps` object gets two new columns
  'Deleted' and 'DeletedReason' that indicate that a lap was deleted and why
  it was deleted.

- The intended total lap count of a race or sprint session is now available
  through :attr:`fastf1.core.Session.total_laps`.
  (by @Toskosz)

- Added method :func:`fastf1.core.Laps.split_qualifying_sessions` to split
  laps for a qualifying session into Q1, Q2 and Q3.

- The F1 timing data API has been added as an additional fallback backend for
  retrieving event schedule data (#260).

- In the event schedule, ``Session*Date`` will now be a timezone-aware local
  timestamp (previously: local, but not timezone-aware). Additionally, for each
  session there now exists a non-timezone aware UTC timestamp in
  ``Session*DateUtc`` (#253). Timezone information and UTC timestamps are only
  available when using one of ``'fastf1'`` or ``'f1timing'`` as backend.

- Added ``strict_search`` parameter to :func:`fastf1.get_event` that disables
  fuzzy matching for exact matching of session names. (by @Neron-png)

- Added track status data as :attr:`fastf1.core.Session.track_status`.
  (by @SpyrosKoun)

- Added function :func:`fastf1.core.Telemetry.add_track_status` for adding
  track status information to telemetry data. (by @SpyrosKoun))

- Added function :func:`fastf1.core.Laps.pick_lap` for conveniently selecting
  specific laps by their lap number. (by @TracingInsights)

- Added a custom ``__repr__`` to :class:`fastf1.core.Session` for a more
  meaningful string representation of the object. Now, information about the
  year, round, event name and session name will be shown. (by @Casper-Guo)

- FastF1 can now be installed using conda-forge. (by @daylinmorgan)

- Added ``HeadshotURL`` and ``CountryCode`` to
  :class:`fastf1.core.SessionResults` and :class:`fastf1.core.DriverResult`.
  (by @lmontrieux)

- Tyre compound colors are now available through
  :attr:`fastf1.plotting.COMPOUND_COLORS`. (by @Caspar-Guo)

- The cache now supports "offline mode" where only cached responses are
  returned and no actual requests are sent even if an internet connection
  is available. Offline mode can be enabled using
  :func:`fastf1.Cache.offline_mode`.

- For race sessions, the previously missing first lap time is now automatically
  added from Ergast (#293).

- For race sessions, lap start and end times are now correctly aligned between
  drivers. Previously, there was a small difference in the order of a few tens
  of milliseconds.

- Add current ``Position`` at the end of each lap to :class:`fastf1.core.Laps`
  and :class:`fastf1.core.Lap` (#295).

- Add official classification as ``ClassifiedPosition`` for Races and Sprints
  to :class:`fastf1.core.SessionResults` and :class:`fastf1.core.DriverResult`.
  The ``ClassifiedPosition`` lists the finishing position for drivers who are
  officially classified or a reason for not being classified, for example if
  a driver retired, was disqualified or similar. (#294)


Other Changes
^^^^^^^^^^^^^

- All columns in :class:`fastf1.core.Laps` that were previously of type ``int``
  are now ``float`` to support ``NaN`` values.


Bug Fixes
^^^^^^^^^

- The API parser will now correctly detect when lap times were deleted and
  will not mark these lap times as personal best time anymore if the deleted
  lap was a drivers fastest lap. (#165)

- Enforce creation of :class:`fastf1.core.Laps` with default columns and
  default dtypes (when created through :func:`fastf1.core.Session.load`)
  (#310).

- Fixed a bug where FastF1 Series-like objects where returned instead of a
  native pandas ``Series`` when getting a single column of a FastF1
  DataFrame-like object by slicing vertically.

- Improve loading of session results when F1 data is partially incomplete.

- Improved type hints throughout FastF1 (by @transorsmth)

- Enforce default column dtypes when creating a new :class:`fastf1.core.Laps`
  object. (#310)

- Fixed an issues were dtypes were always enforced when a new
  :class:`fastf1.core.SessionResults` object was created, even if
  ``force_default_cols=False``.

- Fixed incorrectly set ``_internal_names`` for objects inheriting from
  DataFrame or Series. This potentially caused incorrect warnings about
  incorrectly creating new columns.

- Added missing ``__finalize__`` calls for subclasses of DataFrames and Series
  that resulted in metadata being lost.

- Fixed incorrectly spelled driver name for Hulkenberg. (by @lmontrieux)

- Documentation improvements. (by @lmontrieux)

- Fixed a bug where specific temporary error responses from Ergast where
  cached. This then required the cache to be cleared so that the specific
  API request would work again.

- Fixed a bug where lap times and sector times were missing if the previous
  value was exactly equal

- Fixed a bug in the API parser that created ghost laps with no real data and
  no driver


Backwards Incompatible API Changes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- :func:`fastf1.utils.to_datetime` and :func:`fastf1.utils.to_timedelta` will
  now return ``None`` instead of raising an exception when a string cannot
  be parsed.

- The name of a Sprint session will now always be 'Sprint'. Previously, it was
  'Sprint Qualifying' for the 2021 seasons and 'Sprint' for all subsequent
  seasons.


Removals
^^^^^^^^

The following deprecated API elements have been removed:

- Properties :attr:`fastf1.events.Event.name`,
  :attr:`fastf1.events.Event.date` and :attr:`fastf1.events.Event.gp`

- Creating an :class:`fastf1.events.Event` object by not specifying a the
  ``identifier`` argument for :func:`fastf1.get_session` and
  :func:`fastf1.events.get_session` is no longer supported.

- The argument ``event`` is no longer supported by
  :func:`fastf1.get_session` and :func:`fastf1.events.get_session` and
  replaced by ``identifier``.

- Functions :func:`fastf1.core.get_session` (use
  :func:`fastf1.get_session`) and :func:`fastf1.core.get_round`
  (no replacement) have been removed.

- Methods :func:`fastf1.core.Session.load_laps` and
  :func:`fastf1.core.Session.load_telemetry` have been removed,

- Property :attr:`fastf1.core.Session.weekend` has been removed

- Properties :attr:`fastf1.core.DriverResult.name`,
  :attr:`fastf1.core.DriverResult.familyname`,
  :attr:`fastf1.core.DriverResult.grid`,
  :attr:`fastf1.core.DriverResult.position`,
  :attr:`fastf1.core.DriverResult.team` have been removed

- :class:`fastf1.core.Driver` has been removed

- :class:`fastf1.core.Weekend` has been removed

- :func:`fastf1.ergast.fetch_weekend` has been removed


Performance Improvements
^^^^^^^^^^^^^^^^^^^^^^^^

- performance improvement in :func:``fastf1.api.car_data``
  and :func:``fastf1.api.pos_data``


Deprecations
^^^^^^^^^^^^

- :mod:`fastf1.api` will be considered private in future releases and may be
  removed or changed. Please do not use functionality from :mod:`fastf1.api`.
  If you currently require functionality from there, please open an issue
  on Github with details about what you require and why.

- :mod:`fastf1.utils.delta_time` is considered deprecated and will be modified or
  removed in a future release because it has a tendency to give inaccurate
  results.

---

### Changelog V3.1.X (`docs/changelog/v3.1.x.rst`)

What's new in v3.1.5
--------------------

(released 24/11/2023)

New Features
^^^^^^^^^^^^

- Added driver colors for OWA, DEN, OSU


What's new in v3.1.5
--------------------

(released 17/11/2023)

Bug Fixes
^^^^^^^^^

- Fixed a bug that caused inconsistent behaviour in
  :func:`~fastf1.core.Laps.pick_fastest` in some cases were there was no lap
  that met the criteria for a fastest lap. Now, an empty
  :class:`~fastf1.core.Lap` object will always be returned when there is no
  fastest lap. (Note that this will change in the future, see 'Deprecations'
  below (#476) (by @Casper-Guo)

- Fixed a bug that prevented some sessions of the Las Vegas Grand Prix from
  being loaded (#481)

Deprecations
^^^^^^^^^^^^

- In cases were no lap meets the criteria for a fastest lap,
  :func:`~fastf1.core.Laps.pick_fastest` currently returns an empty
  :class:`~fastf1.core.Lap` object. Starting from version 3.3, this will
  return ``None`` instead


What's new in v3.1.4
--------------------

(released 26/10/2023)

Bug Fixes
^^^^^^^^^

- Fixed a bug that caused :func:`~fastf1.core.Telemetry.add_driver_ahead` to
  only work with telemetry data that matches the sampling timebase of the
  car data (#430)

- Improved robustness of the Ergast API parser to prevent crashes caused by some
  empty values in the API response (#433) (by @harningle)

- Fixed: some laps that were generated by FastF1 had incorrect lap numbers

- Fixed: pit out times from the lap onto the grid are no longer shown for the
  first lap of a race-like session. The first lap will only have a pit out time
  if a driver started from the pit lane or pitted on the formation lap.
  (#467) (by @Casper-Guo)

- Improved robustness of the 'f1timing' schedule backend to prevent a crash
  caused by partially incorrect data for the schedule of the Qatar GP

- Fixed: laps for all drivers were marked as inaccurate if the lap accuracy
  check could not be performed for one driver


New Features
^^^^^^^^^^^^

- Added driver colors for VES, POU, HAD, DOO and BEA
  (#471) (by @pesaventofilippo)



What's new in v3.1.3
--------------------

(released 07/10/2023)

Bug Fixes
^^^^^^^^^

- fixed a bug in the driver list parser that caused Piastri to be missing from
  the results in the 2023 Qatar Sprint Shootout (#460)



What's new in v3.1.2
--------------------

(released 31/08/2023)

Bug Fixes
^^^^^^^^^

- temporarily restrict Pandas<2.1.0 due to unexpected API changes



What's new in v3.1.1
--------------------

(released 29/08/2023)


Hotfix to correct incorrect package definition that prevented import of FastF1.



What's new in v3.1.0
--------------------

(released 29/08/2023)

New Features
^^^^^^^^^^^^

- Added additional circuit information that includes the location of corners,
  marshal lights, marshal sectors and the rotation of the track map. This
  data is available through :func:`fastf1.core.Session.get_circuit_info`. Also
  check out the new examples that show how to annotate your plots using this
  data.
  A huge thank you to @multiviewer (https://multiviewer.app/) for providing
  this information through MultiViewer's API.

- "SessionInfo" data from the F1 livetiming API is now available through
  :attr:`fastf1.core.Session.session_info`

- Added driver colors for Shwartzman and Lawson (by @pesaventofilippo) (#441)

- Various improvement to the ``Laps.pick_*`` methods to make it easier to select
  specific laps from :class:`~fastf1.core.Laps` (by @Casper-Guo) (#376).

  **New** (no equivalent has existed before)

  - :func:`~fastf1.core.Laps.pick_not_deleted` for selecting all laps that
    haven't been deleted

  **New** (these methods replace methods that only accepted single values; the
  new functions accept single values or lists of values)

  - :func:`~fastf1.core.Laps.pick_laps` for selecting one or multiple laps
    by their lap number; replaces :func:`~fastf1.core.Laps.pick_lap`

  - :func:`~fastf1.core.Laps.pick_drivers` for selecting laps from one or
    multiple drivers; replaces :func:`~fastf1.core.Laps.pick_driver`

  - :func:`~fastf1.core.Laps.pick_compounds` for selecting laps driven on one or
    multiple compounds; replaces :func:`~fastf1.core.Laps.pick_tyre`

  **Improved**

  - :func:`~fastf1.core.Laps.pick_track_status` now has additional options for
    the ``how`` argument to exclude laps with a specific track status or match
    or exclude laps with one of multiple track status values.


Performance
^^^^^^^^^^^

- greatly improved speed when parsing car data and position data


Bug Fixes
^^^^^^^^^

- Fixed :func:`~fastf1.core.Laps.split_qualifying_sessions` returns
  incorrect result

- Fixed incorrect calculation of results for Qualifying-like sessions (#429)

- Fixed incorrect alignment of lap start/end times that causes shifted telemetry
  data when comparing laps and incorrect results for calculated grid positions
  (#440)

- Fixed an unhandled exception in the lap timing parser that made it impossible
  to load data for the 2020 Miami Qualifying (#431)

- Fixed incorrectly set lap start times after some red flag restarts

- Fixed a bug that could prevent data loading in case of partially missing data


Deprecations
^^^^^^^^^^^^

- Deprecated :func:`fastf1.core.Laps.pick_lap`

- Deprecated :func:`fastf1.core.Laps.pick_driver`

- Deprecated :func:`fastf1.core.Laps.pick_tyre`


Other Changes
^^^^^^^^^^^^^

- Fixed some errors in the documentation (by @dawiddzhafarov, @RyanHaniff)
  (#439, #402)

- Fixed some examples to no longer use deprecated arguments (by @wakamex) (#423)

- Fixed an error in the SignalRClient example (by @erdieee) (#421)

- Added a new team pace ranking example (by @Casper-Guo) (#420)

---

### Changelog V3.2.X (`docs/changelog/v3.2.x.rst`)

What's new in v3.2.2
--------------------

(released 09/02/2024)


Bug Fixes
^^^^^^^^^

- Fixed another bug that caused :meth:`fastf1.core.Session.get_circuit_info`
  to fail only in some cases if the default resampling frequency for
  telemetry data is changed (#455)


What's new in v3.2.1
--------------------

(released 05/02/2024)


Bug Fixes
^^^^^^^^^

- Fixed a bug that caused timestamps of telemetry data to have (apparent)
  microseconds precision (even though this is not the case). As a result,
  merging position data and car data did not have a well matching timestamp
  index resulting in additional interpolated values. This problem only occurred
  in combination with recent versions of Pandas.

Other
^^^^^

- Various changes to address deprecations in Pandas.


What's new in v3.2.0
--------------------

(released 07/01/2024)


New Features
^^^^^^^^^^^^

- Added support for Pandas version v2.1.0 and higher.

- Methods :meth:`fastf1.core.Lap.get_telemetry` and
  :meth:`fastf1.core.Laps.get_telemetry` now take an optional additional
  ``frequency`` keyword argument to override the default frequency that is
  used for resampling.

- Added :meth:`fastf1.core.Laps.pick_box_laps` to select inlaps and outlaps
  (#454) (by @pesaventofilippo)

- Added the lap number to race control messages, see
  :attr:`fastf1.core.Session.race_control_messages` (#475) (by @manpean)

- Improved lap data integrity checks (#449) (by @d-tomasino)

- Added a string representation for the Cache class that gives information
  about the cache path and the cache size

- Added the function :func:`fastf1.Cache.get_cache_info` that returns
  information about the cache path and the cache size


Bug Fixes
^^^^^^^^^

- Fixed incorrect lap number (zero instead of one) for generated laps that are
  added when a driver crashes on the very first lap

- Fixed :meth:`fastf1.core.Session.get_circuit_info` fails if the default
  resampling frequency for telemetry data is changed (#455)

- Fixed multiple issues with the Ergast API interface that resulted in
  invalid request being made and consequently no data being returned
  (#489, #494) (by @Lombardoc4)

- Fixed missing driver information for drivers that did not start in a race
  (classified as DNS - did not start) (#447)

- Fixed a regression introduced in v3.1.3 that caused the ``CountryCode``
  to be missing from :class:`fastf1.core.SessionResults`

- Fixed a compatibility issued with Pandas v1.3.5

---

### Changelog V3.3.X (`docs/changelog/v3.3.x.rst`)

What's new in v3.3.9
--------------------

(released 05/07/2024)

New Features
^^^^^^^^^^^^

- Added support for driver Franco Colapinto (COL) (by @grahamjwhite) (#609)


What's new in v3.3.8
--------------------

(released 10/06/2024)

Bug Fixes
^^^^^^^^^

- Resolved an issue where the majority of data was missing from the 2024
  Sprint Qualifying session results (fixes #597).


What's new in v3.3.7
--------------------

(released 28/05/2024)


Bug Fixes
^^^^^^^^^

- Fixed a bug that caused the timing data for the first lap of the Monaco GP
  2024 to be missing entirely (fixes #579)


What's new in v3.3.6
--------------------

(released 16/05/2024)


Bug Fixes
^^^^^^^^^

- Laps where a driver crashes and retires on track now contain a correct
  track status (fixes #575)

- Fixed previously incorrect circuit info for Mugello 2020 (fixes #563)


Others
^^^^^^

- Improved a warning message that informs about missing data when calculating
  qualification results


What's new in v3.3.5
--------------------

(released 19/04/2024)


Bug Fixes
^^^^^^^^^

- Fixed an issue that causes no result data to be available for
  'Sprint Qualifying' sessions

- Correctly handle reinstated lap times after they were previously deleted


What's new in v3.3.4
--------------------

(released 17/04/2024)


Bug Fixes
^^^^^^^^^

- Correctly support the new "Sprint Qualifying"


What's new in v3.3.3
--------------------

(released 05/04/2024)


New Features
^^^^^^^^^^^^

- Added support for driver Ayumu Iwasa (IWA)


What's new in v3.3.2
--------------------

(released 26/03/2024)


Bug Fixes
^^^^^^^^^

- Fixed a bug that caused the track status values for each lap to be sometimes
  incorrect in the 'TrackStatus' column of the :class:`~fastf1.core.Laps`
  DataFrame (fixes #557 and more).


What's new in v3.3.1
--------------------

(released 10/03/2024)


Bug Fixes
^^^^^^^^^

- Fix: correctly handle empty strings when parsing them in
  :func:`fastf1.utils.to_datetime` (by @erdieee) (#531)

- Fix: gracefully handle empty strings when parsing datetime values in
  Ergast responses (by @mdsakalu) (#546). This fixes partially missing data
  in the results Qualifying and Race results for the 2024 Saudi Arabia GP.



What's new in v3.3.0
--------------------

(released 19/02/2024)


New Features
^^^^^^^^^^^^

- Updated team names and team colors for the 2024 season. (As usual, this means
  that this information is no longer valid for the previous season!)

- Improved the accuracy of :func:`fastf1.utils.delta_time` (by @grahamjwhite)
  (#512)

---

### Changelog V3.4.X (`docs/changelog/v3.4.x.rst`)

What's new in v3.4.5
--------------------

(released 26/02/2025)

Bug Fixes
^^^^^^^^^

- Add workaround to support 2025 pre-season testing sessions


What's new in v3.4.4
--------------------

(released 17/11/2024)

Bug Fixes
^^^^^^^^^

- Use a custom user agent when requesting event schedule data from Github to
  prevent the request from being blocked in some environments. (see #656)


What's new in v3.4.3
--------------------

(released 03/11/2024)

Bug Fixes
^^^^^^^^^

- Added a workaround to fix an issue that made it impossible to load any data
  for the Qualifying of the 2024 Sao Paulo Grand Prix (closes #652).


What's new in v3.4.2
--------------------

(released 27/10/2024)

Bug Fixes
^^^^^^^^^

- Fixed a bug that prevented getting the team color for "RB" in some
  situations. (by @Casper-Guo) (#645)

- Improved some warning messages related to team name matching in the plotting
  submodule. (by @Casper-Guo) (#645)


What's new in v3.4.1
--------------------

(released 16/10/2024)

Bug Fixes
^^^^^^^^^

- Fixed a bug that caused qualifying laps to be split incorrectly into Q1, Q2
  and Q3 laps. Mainly outlaps were incorrectly assigned to the previous
  session. (closes #605)

- Fixed errors in tyre data (compound, tyre age, ...). (Massive thanks to
  user "TheBobba" on the MultiViewer Discord for noticing and helping me with
  this!)

- Added error handling for a rare error caused by downgrading the
  ``requests-cache`` dependency or by reusing the cache with various versions
  of the dependency.


Other Changes
^^^^^^^^^^^^^

- Bumped some DeprecationWarnings to FutureWarnings to make them more visible
  to users.


What's new in v3.4.0
--------------------

(released 26/07/2024)


New Features
^^^^^^^^^^^^

- Completely reimplemented the :mod:`fastf1.plotting` module. The new module
  provides a more flexible and powerful API for creating custom plots. This
  is an overview of the relevant new features and changes:

    - Driver and team names, abbreviations and colors are now supported for
      all seasons since 2018 instead of only for the most recent season.

    - Driver changes and test drivers running in free practice session are now
      supported automatically and do no longer require an update of FastF1.

    - Users can now choose between the "official" F1 color map and the color map
      that was already used previously by FastF1.

    - Driver specific colors are deprecated. Users are encouraged to use more
      visually distinct plot styling options instead to differentiate between
      drivers of the same team. The new
      :func:`~fastf1.plotting.get_driver_style` function can be used to easily
      get driver specific styling options.

    - Users can override team colors and short name constants on a per-session
      basis.

    - The API has been improved to be more consistent and easier to use.

- Added support for a fallback mirror for the F1 livetiming API. If the primary
  API is unavailable, FastF1 will automatically switch to the fallback mirror
  and continue to work without any user intervention.
  This feature is experimental and for now provided without any guarantees.

- Added a warning that informs users when event, driver or team names are
  fuzzy matched. (by @Casper-Guo) (#574)

- Improved fuzzy matching of event names to give better matching results. (by
  @Casper-Guo) (#579)

- Added support for Numpy v2.0.

- The SignalRClient can now be started when an async event loop is already
  running by awaiting the new
  :func:`fastf1.livetiming.client.SignalRClient.async_start` coroutine. This
  enables usage in newer versions of Juypter Notebooks, for example.

- Set a default connection timeout of five seconds for all requests to the
  Ergast API. This should prevent long data loading times when the API is
  unresponsive.


Bug Fixes
^^^^^^^^^

- Drivers that crashed on the very first lap are now assigned ``NaN`` as their
  position, ensuring correct positions throughout the field at then end of the
  first lap. (by @AND2797) (#595)

- Fixed a bug that prevented loading of any data when driver information was
  unavailable from the F1 livetiming API.

- Fixed a bug in the client side rate limiting that allowed higher rates than
  intended. This may have caused the client to be temporarily blocked by the
  server.


Deprecations
^^^^^^^^^^^^

- The following module level properties of :mod:`fastf1.plotting` have been
  deprecated:
  :attr:`~fastf1.plotting.COMPOUND_COLORS`,
  :attr:`~fastf1.plotting.DRIVER_COLORS`,
  :attr:`~fastf1.plotting.DRIVER_TRANSLATE`,
  :attr:`~fastf1.plotting.TEAM_COLORS`,
  :attr:`~fastf1.plotting.TEAM_TRANSLATE`,
  :attr:`~fastf1.plotting.COLOR_PALETTE`


- The following functions in :mod:`fastf1.plotting` have been deprecated:
  :func:`~fastf1.plotting.driver_color`,
  :func:`~fastf1.plotting.team_color`,
  :func:`~fastf1.plotting.lapnumber_axis`

- The argument ``misc_mpl_mods`` of function :func:`~fastf1.plotting.setup_mpl`
  is deprecated and will be removed in the future without replacement for its
  functionality.

- The argument ``color_scheme`` of function :func:`~fastf1.plotting.setup_mpl`
  will default to ``None`` in the future, meaning that FastF1's default color
  scheme will need to be enabled explicitly.


Increased minimum versions for dependencies
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- The new minimum version of Python is 3.9. Support for Python 3.8 is dropped.
- The minimum versions for the following dependencies have been increased:

  - numpy to >=1.23.1
  - scipy to >=1.8.1

---

### Changelog V3.5.X (`docs/changelog/v3.5.x.rst`)

What's new in v3.5.3
--------------------

(released 16/03/2025)

Bug Fixes
^^^^^^^^^

- Fixed incorrect number of total laps (``Session.total_laps``) for the
  2025 Grand Prix of Australia.

- Fixed incorrectly added 58th lap for Norris in the 2025 Grand Prix of
  Australia.


What's new in v3.5.2
--------------------

(released 14/03/2025)

Bug Fixes
^^^^^^^^^

- Use yellow instead of red as team color for Racing Bulls in the 2025 season
  to better distinguish the color from others. (by @pesaventofilippo) (#707)

- Switch to a linear interpolation that considers sample timestamps correctly
  when merging/resampling telemetry data.


What's new in v3.5.1
--------------------

(released 13/03/2025)


New Features
^^^^^^^^^^^^

- :func:`~fastf1.plotting.get_driver_style` now replaces the magic ``'auto'``
  color keyword recursively. This allows for more complex plotting styles, for
  example when using the Plotly library. (by @Casper-Guo) (#701)


Bug Fixes
^^^^^^^^^

- Missing drivers are now only added to session results based on data from
  Jolpica-F1 (formerly Ergast), when the session type is fully supported by
  the API. This fixes cases where drivers were incorrectly added in practice
  sessions, for example. (by @Casper-Guo) (#699)



What's new in v3.5.0
--------------------

(released 01/03/2025)


New Features
^^^^^^^^^^^^

- The backend for the Ergast API is now changed to its successor Jolpica-F1
  (see https://github.com/jolpica/jolpica-f1 ) to ensure continued support for
  the 2025 season and later seasons.

- Added team colors for the 2025 season. (by @Casper-Guo) (#690)


Bug Fixes
^^^^^^^^^

- Incorrect and inconsistent data types in various places have been fixed. The
  dtypes of all DataFrames after data loading now always match the dtypes that
  are defined in the documentation. Some dtypes may have changed as a result
  of this fix.

- Fixed lap time alignment failures in some edge cases.


Backwards Incompatible Changes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- ``Laps.pick_fastest()`` will now return ``None`` if no fastest lap exists, as
  announced previously.
  Previously, an empty ``Lap`` object was returned.


Maintenance
^^^^^^^^^^^

- Addressed upcoming changes in pandas and fixed a related deprecation warning
  caused by implicit type coercion. (by @Casper-Guo) (#676, #682)

- Temporarily pinned ``websockets`` to version 14 or older to prevent issues
  with live timing recording.

---

### Changelog V3.6.X (`docs/changelog/v3.6.x.rst`)

What's new in v3.6.1
--------------------

(released 05/09/2025)


Bug Fixes
^^^^^^^^^

- Fix an error when generating the driver-team mapping for plotting constants
  (caused by incorrect source data in the 2025 Monza FP1).


What's new in v3.6.0
--------------------

(released 08/07/2025)


New Features
^^^^^^^^^^^^

- The number of laps that each driver completed in a race or sprint session is
  now available in :class:`~fastf1.core.SessionResults`, accessible through
  :attr:`~fastf1.core.Session.results`, in a new ``Laps`` column. (#766)

- :func:`fastf1.get_events_remaining` now correctly considers the current time
  of day and the starting time of the last session of an event to determine
  the remaining events. (#750) (by @VLADOZXD)

- Preliminary Race and Sprint results are now calculated from timing data when
  no official results data is available from Jolpica-F1.
  (#737) (by @Casper-Guo)


Bug Fixes
^^^^^^^^^

- Fixed a bug where incorrect positions were calculated for all drivers at the
  end of the first lap in the 2025 British GP (#765)

- Added additional logic to detect and correct incorrect tyre information in
  the source data of the 2025 Australian GP Race and the 2025 Miami GP
  Sprint (#746)

- The API parser will now calculate missing lap times from existing sector
  times if possible when the source data explicitly indicates a missing lap
  time by providing an empty lap time object. This fixes data errors caused by
  transponder issues with RUS car at the 2025 Bahrain GP. (#740)

- The team name matching used with the plotting functionality now additionally
  considers the team short names to fix problems with the short "RB F1 Team"
  name. (#726) (by @Casper-Guo)


Removals
^^^^^^^^

According to the deprecation timeline, the following functionality has been
removed after it was marked as deprecated in v3.4.0.

- The following module level properties of :mod:`fastf1.plotting` have been
  removed:
  ``COMPOUND_COLORS``
  ``DRIVER_COLORS``
  ``DRIVER_TRANSLATE``
  ``TEAM_COLORS``
  ``TEAM_TRANSLATE``
  ``COLOR_PALETTE``

- The following functions in :mod:`fastf1.plotting` have been removed:
  ``driver_color()``
  ``team_color()``
  ``lapnumber_axis()``

- The argument ``misc_mpl_mods`` of function :func:`~fastf1.plotting.setup_mpl`
  has been removed without replacement for its functionality.

- The argument ``color_scheme`` of function :func:`~fastf1.plotting.setup_mpl`
  now defaults to ``None``.


Maintenance
^^^^^^^^^^^

- Addressed upcoming changes in pandas and fixed a related deprecation warning
  caused by implicit type coercion. (by @Casper-Guo) (#727)


Miscellaneous
^^^^^^^^^^^^^

- Updated the "Who can still win the drivers WDC" example to use the 2025
  season. (#763) (by @faustocalvinio)

- Added a new "Season Summary Visualization" example to the gallery. (#661)
  (by @eatwhatyoukill and @Casper-Guo)

- Documentation improvements (by @Casper-Guo)

---

### Changelog V3.7.X (`docs/changelog/v3.7.x.rst`)

What's new in v3.7.0
--------------------

(released 28/11/2025)


New Features
^^^^^^^^^^^^

- Python 3.14 is now officially supported.

- Major overhaul of the documentation with changes to the overall structure and design. Support for switching between
  multiple documentation versions is available going forward from now.

- The livetiming client now uses a new endpoint and protocol. This follows changes by Formula 1, who have
  gradually phased out the old endpoints.

- Support for authentication with an F1TV Access/Pro/Premium subscription has been added. Authentication is only
  required when using the new live timing client, since the new endpoints no longer allow unauthenticated access. This
  change has no effect on the majority of users who only load data after a session has ended.


Bug Fixes
^^^^^^^^^

- Improved handling of unexpected data types in the Jolpica/Ergast API client to prevent crashes caused by
  incorrect or unexpected external data. (#814)

- Fixed a bug that caused the "auto-cast" feature of the Ergast API client to not cast values of any objects
  that were contained inside a JSON array. This bug was only encountered when using raw responses instead of
  DataFrames. (#797)

- Various bugs related to usage of the live timing client and loading of created recordings have been fixed.

---

### Contributing Ai Policy (`docs/contributing/ai_policy.rst`)

.. _ai-policy:


*********
AI Policy
*********

AI-based tools can help to make developers more productive. But current tools
are still unable to make meaningful changes in a complex code base without
significant human oversight. Human judgement and contextual understanding
are very important for a good contribution.

When making any contributions to FastF1, adhere to the guidelines that are
detailed below.

Pull requests and issues that appear to violate these guidelines may be
closed without review or comment by the maintainers. Accounts that repeatedly
violated these guidelines may be blocked.


Responsibility
==============

You must be able to understand your own code and you must be able to
understand related parts of the existing source code. Ensure that your
code meets the code quality standards for FastF1. You are fully responsible
for the contributions that you submit to FastF1.


Communication
=============

Communicate in your own words. Do not use AI to write comments, pull
request descriptions or issue descriptions. Using AI for this makes
it much more difficult to judge your contribution.
If you use AI for translation or grammar correction, please keep the
wording as close as possible to the original wording.


Disclosure
==========

Disclose your usage of AI. Specify what tool(s) you used, how you used them
and what code or text is AI generated.


Copyright
=========

Code generated by AI may infringe on copyright of a third party. It is your
responsibility to not infringe. When in doubt, remember that code that you
write yourself, without AI tools, is your work and does not infringe.


AI Agents
=========

Do not submit fully AI generated pull requests! Don't just act as a proxy for
an AI tool. Maintainers can interact with these tools directly, if they wish
to do so. Submitting fully AI generated pull requests is a waste of reviewers
time.


Acknowledgement and Other Resources
===================================

Thank you to the developers of NumPy, SciPy, Matplotlib and various other libraries
for providing significant inspiration for these guidelines.

If you are interested in reading more about the pitfalls that can be associated with
using AI to create contributions on open source projects, here are some additional
resources:

- https://blog.scientific-python.org/scientific-python/community-considerations-around-ai/
- https://github.com/melissawm/open-source-ai-contribution-policies

---

### Contributing Coding Guide (`docs/contributing/coding_guide.rst`)

.. _pr-guidelines:

***********************
Pull request guidelines
***********************

Pull requests (PRs) are the mechanism for contributing to FastF1s code and
documentation.

Summary for PR authors
======================

.. note::

   * We value contributions from people with all levels of experience. In
     particular if this is your first PR not everything has to be perfect.
     We'll guide you through the PR process.
   * Nevertheless, try to follow the guidelines below as well as you can to
     help make the PR process quick and smooth.
   * Be patient with reviewers. We try our best to respond quickly, but we
     have limited bandwidth. If there is no feedback within a couple of days,
     please ping us by posting a comment to your PR.
   * Do not submit fully AI generated pull requests. Please read the :ref:`ai-policy`.

When making a PR, pay attention to:

.. rst-class:: checklist

* Adhere to the :ref:`coding_guidelines`.
* Update the :ref:`documentation <pr-documentation>` if necessary.
* Aim at making the PR as "ready-to-go" as you can. This helps to speed up
  the review process.
* It is ok to open incomplete or work-in-progress PRs if you need help or
  feedback from the developers. You may mark these as
  `draft pull requests <https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests>`_
  on GitHub.
* When updating your PR, instead of adding new commits to fix something, please
  consider amending your initial commit(s) to keep the history clean.
  You can achieve this using

  .. code-block:: bash

     git commit --amend --no-edit
     git push [your-remote-repo] [your-branch] --force-with-lease

See also :ref:`contributing` for how to make a PR.

.. _pr-guidelines-details:

Detailed guidelines
===================

.. _pr-documentation:

Documentation
-------------

* Every new feature should be documented.  If it's a new module, don't
  forget to add a new rst file to the API docs.

* Each high-level function should have a small example in
  the ``Examples`` section of the docstring.  This should be as simple as
  possible to demonstrate the method.  More complex examples should go into
  a dedicated example file in the :file:`examples` directory, which will be
  rendered to the examples gallery in the documentation.

* Build the docs and make sure all formatting warnings are addressed.

* See :ref:`documenting-fastf1` for our documentation style guide.

* If your change is a major new feature, update
  :file:`docs/changelog.rst`.

.. _pr-automated-tests:

Automated tests
---------------

Whenever a pull request is created or updated, various automated test tools
will run on all supported versions of Python.

Make sure that all test are passing. (All checks are listed at the bottom of
the GitHub page of your pull request)

---

### Contributing Contributing (`docs/contributing/contributing.rst`)

.. _contributing:

============
Contributing
============


The community around FastF1 is slowly building and everyone is welcome to
contribute to the project.

.. note::
    Before making contributions to FastF1, please read the :ref:`ai-policy`.


Submitting a bug report
=======================

If you find a bug in the code or documentation, do not hesitate to open a
new issue in the `issue section <https://github.com/theOehrly/Fast-F1/issues>`_
on Github. You are also welcome to post feature requests or pull requests.

If you have more general questions or problems that likely are not caused by
a bug in FastF1, you can open a new
`discussion <https://github.com/theOehrly/Fast-F1/discussions>`_ instead.


If you are reporting a bug, please do your best to include the following:

- A short, top-level summary of the bug. In most cases, this should be 1-2
  sentences.

- A short, self-contained code snippet to reproduce the bug, ideally allowing
  a simple copy and paste to reproduce. Please do your best to reduce the code
  snippet to the minimum required.

- The actual outcome of the code snippet.

- The expected outcome of the code snippet.

- The FastF1 version and Python version that you are using.
  You can grab the version with the following commands::

      >>> import fastf1
      >>> fastf1.__version__  # doctest: +SKIP
      '2.2.1'
      >>> import platform
      >>> platform.python_version()  # doctest: +SKIP
      '3.9.2'


We have preloaded the issue creation page with a Markdown template that you
can use to organize this information.

Thank you for your help in keeping bug reports complete, targeted and
descriptive.


Requesting a new feature
========================

Please post feature requests in the
`issue section <https://github.com/theOehrly/Fast-F1/issues>`_ on Github.

Since FastF1 is an open source project with limited resources, you are
encouraged to also participate in the implementation as much as you can.


.. _contributing-code:

Contributing code
=================

.. _how-to-contribute:

How to contribute
-----------------

The preferred way to contribute to FastF1 is to fork the `main
repository <https://github.com/theOehrly/Fast-F1/>`__ on GitHub,
then submit a "pull request" (PR).

A brief overview is:

1. `Create an account <https://github.com/join>`_ on GitHub if you do not
   already have one.

2. Fork the `project repository <https://github.com/theOehrly/Fast-F1>`_:
   click on the 'Fork' button near the top of the page. This creates a copy of
   the code under your account on the GitHub server.

3. Clone this copy to your local disk::

      git clone https://github.com/<YOUR GITHUB USERNAME>/Fast-F1.git

4. Enter the directory and install the local version of FastF1.
   See :ref:`installing_for_devs` for instructions

5. Create a branch to hold your changes::

      git checkout -b my-feature origin/main

   and start making changes. Never work in the ``main`` branch!

6. Work on this copy, on your computer, using Git to do the version control.
   When you're done editing e.g., ``fastf1/core.py``, do::

      git add fastf1/core.py
      git commit

   to record your changes in Git, then push them to GitHub with::

      git push -u origin my-feature

Finally, go to the web page of your fork of the FastF1 repo, and click
'Pull request' to send your changes to the maintainer for review.

.. seealso::

  * `Git documentation <https://git-scm.com/doc>`_
  * `Git-Contributing to a Project <https://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project>`_
  * `Introduction to GitHub  <https://lab.github.com/githubtraining/introduction-to-github>`_


Contributing pull requests
--------------------------

It is recommended to check that your contribution complies with the following
rules before submitting a pull request:

* If your pull request addresses an issue, please use the title to describe the
  issue and mention the issue number in the pull request description to ensure
  that a link is created to the original issue.

* All public methods should have informative docstrings with sample usage when
  appropriate. Use the `google docstring standard
  <https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html>`_.

* Formatting should follow the recommendations of PEP8_, as enforced by
  ruff_. The maximum line length for all changed lines is 79 characters.
  You can check code style compliance from the command line with ::

    python -m pip install ruff
    ruff check .

  or your editor may provide integration with it. The above command will not
  flag lines that are too long!

  Ruff will also be run before each commit if you have the pre-commit hooks
  installed (see :ref:`install_pre_commit`).

  .. _PEP8: https://www.python.org/dev/peps/pep-0008/
  .. _ruff: https://docs.astral.sh/ruff/

* Changes (both new features and bugfixes) should have good test coverage. See
  :ref:`testing` for more details.

* Import the following modules using the standard scipy conventions::

     import numpy as np
     import pandas as pd
     import matplotlib as mpl
     import matplotlib.pyplot as plt

* If your change is a major new feature, add an entry to the ``Changelog``
  section by editing ``docs/changelog.rst``

.. note::

    The current state of the FastF1 code base is not compliant with all
    of those guidelines, but we expect that enforcing those constraints on all
    new contributions will move the overall code base quality in the right
    direction.

.. seealso::

  * :ref:`coding_guidelines`
  * :ref:`testing`
  * :ref:`documenting-fastf1`


.. _contributing_documentation:

Contributing documentation
==========================

You as an end-user of FastF1 can make a valuable contribution because you
more clearly see the potential for improvement than a core developer.
For example, you can:

- Fix a typo
- Clarify a docstring
- Write or update an :ref:`example plot <contributing_gallery_examples>`

The documentation source files live in the same GitHub repository as the code.
Contributions are proposed and accepted through the pull request process.
For details see :ref:`how-to-contribute`.

If you have trouble getting started, you may instead open an `issue`_
describing the intended improvement.

.. _issue: https://github.com/theOehrly/Fast-F1/issues

.. seealso::
  * :ref:`documenting-fastf1`


.. _contributing_gallery_examples:

Contributing examples to the gallery
------------------------------------

FastF1 uses `Sphinx-Gallery <https://sphinx-gallery.github.io/stable/index.html>`_
to generate a gallery of examples. The examples gallery is generated from the
files located in the :file:`examples` folder. To add a new gallery example,
create a new python file in this directory. The file should contain all the
code required to plot the examples. Check out the documentation of
Sphinx-Gallery to find out how to format your example code to include headings,
sections and explanatory text for your example.


.. _coding_guidelines:

Coding guidelines
=================

Supported versions of Python and dependencies
---------------------------------------------

This project supports:

- All minor versions of Python released 42 months prior to the project, and at
  minimum the two latest minor versions.

- All minor versions of Numpy, Pandas and Matplotlib released in the 24 months
  prior to the project, and at minimum the last three minor versions.

- For other dependencies: As a guideline, this project will try to support all
  minor versions initially released in the 12 months prior to our planned
  release date or the oldest that supports our minimum Python. We will only
  bump these dependencies as we need new features or the old versions are no
  longer compatible with other minimum version requirements of this project.

These guidelines are based on `NEP 29`__ .

__ https://numpy.org/neps/nep-0029-deprecation_policy.html


API changes
-----------

API consistency and stability are of great value. Therefore, API changes
(e.g. signature changes, behavior changes, removals) will only be conducted
if the added benefit is worth the user effort for adapting.

API changes in FastF1 have to be performed following the deprecation process
below, except in very rare circumstances as deemed necessary by the developers.
This ensures that users are notified before the change will take effect and thus
prevents unexpected breaking of code.

Note that FastF1 often needs to be adapted to changes in external APIs which
may come without prior warning. To be able to efficiently keep up with these
external changes, it can be necessary to make changes to FastF1 on shorter
notice than described below. In general, breaking changes and deprecations
should be avoided if possible and users should be given prior warnings and as
much time as possible to adapt.


Rules
~~~~~

- Deprecations are targeted at the next minor release (e.g. 3.x)
- Deprecated API is generally removed two minor releases
  after introduction of the deprecation. Longer deprecations can be imposed by
  core developers on a case-by-case basis to give more time for the transition
- The old API must remain fully functional during the deprecation period
- If alternatives to the deprecated API exist, they should be available
  during the deprecation period


Introducing
~~~~~~~~~~~

1. Announce the deprecation in the changelog
   :file:`docs/changelog.rst` (reference your pull request as well)
2. If possible, issue a warning when the deprecated
   API is used, using the python `warnings` module. The correct warning levels
   are:

    - `DeprecationWarning` for the first minor release where the deprecation is
      announced. These warnings are mostly not shown to end users by default
      (depending on how a function is called) but are shown to developers.

    - `FutureWarning` starting from the second minor release where the
      deprecation is announced. These warnings are always shown to end users
      and developers.

Expiring
~~~~~~~~

1. Announce the deprecation in the changelog
   :file:`docs/changelog.rst` (reference your pull request as well)
   For the content, you can usually copy the deprecation notice
   and adapt it slightly.
2. Change the code functionality and remove any related deprecation warnings.

Adding new API
--------------

Every new function, parameter and attribute that is not explicitly marked as
private (i.e., starts with an underscore) becomes part of FastF1's public
API. As discussed above, changing the existing API is cumbersome. Therefore,
take particular care when adding new API:

- Mark helper functions and internal attributes as private by prefixing them
  with an underscore.
- Carefully think about good names for your functions and variables.
- Try to adopt patterns and naming conventions from existing parts of the
  FastF1 API.
- Consider making as many arguments keyword-only as possible. See also
  `API Evolution the Right Way -- Add Parameters Compatibly`__.

  __ https://emptysqua.re/blog/api-evolution-the-right-way/#adding-parameters


New modules and files: installation
-----------------------------------

* If you have added new files or directories, or reorganized existing
  ones, make sure the new files are included in the match patterns in
  in *packages* in :file:`setup.cfg`.


.. _using_logging:

Using logging for debug messages
--------------------------------

FastF1 uses a logging system that is based on the standard Python `logging`
library to write verbose warnings, information, and debug messages.
Please use it! In all those places you write `print` calls to do your
debugging, try using `logger.debug` instead!

FastF1 creates one main logger and then uses child loggers for each module.

To include logging in your module, at the top of the module, you need to add
``from fastf1.logger import get_logger``.  Then calls in your code like::

  # set up the logger once (!)
  logger = get_logger(__name__)

  # code
  logger.info('Here is some information')
  logger.debug('Here is some more detailed information')
  # more code

will log to a logger named ``fastf1.yourmodulename``.


Which logging level to use?
~~~~~~~~~~~~~~~~~~~~~~~~~~~

There are five levels at which you can emit messages.

- `logger.critical` and `logger.error` are really only there for errors that
  will end the use of the library but not kill the interpreter.
- `logger.warning` is used to warn the user, for example, if an operation has
  failed gracefully, if some action is likely to have unintended side-effects
  or similar.
- `logger.info` is for information that the user may want to know if the
  program behaves oddly. For instance, if a driver did not participate in a
  session, some data cannot be loaded for this specific driver. But FastF1 can
  still be used normally with data of all other drivers in this session.
- `logger.debug` is the least likely to be displayed, and hence can be the
  most verbose. Information that is usually only required for development
  and debugging of FastF1 should be logged here.

By default, in FastF1, logging displays all log messages at levels higher than
``logging.INFO`` to `sys.stderr`.

.. _logging tutorial: https://docs.python.org/3/howto/logging.html#logging-basic-tutorial


Allowing optional functions to fail gracefully
----------------------------------------------

FastF1 processes lots of data that may change unexpectedly, contain unknown
values or that is not always available. Of course, the best way to deal with
this is to write code that is as robust as possible. But of course, it is not
always possible to foresee what unexpected data your code might need to deal
with. In some cases, FastF1 cannot work without some specific data being
processed correctly. But in other cases, FastF1 can still be used with limited
functionality if we prevent it from crashing when such an error is encountered.
Examples for such cases are:

- loading optional data: weather data, telemetry, ...
- doing additional (cross) validation of data
- applying corrections to improve the accuracy of data
- ...

If such a task fails, we want FastF1 to show a warning to the user. But
especially if such an error is encountered during data loading, it should not
crash FastF1 and make the whole session unavailable to the user. Loading
incomplete data is always preferred over loading no data at all.

To deal with this, FastF1 provides a special function decorator called
:func:`fastf1.logger.soft_exceptions` that can be used as follows::

  from fastf1.logger import soft_exceptions


  @soft_exceptions(descr_name="optional data processing",
                   msg="Failed to do some optional data processing",
                   logger=logger)
  def _optional_data_loading():
      ...
      return

The basic functionality of this decorator is to wrap a one big
`try: ... except Exception: ...` clause around the function call.
But additionally, if the function call fails, the `msg` is shown to the user,
using the logging level `WARNING`. The traceback is logged with the logging
level `DEBUG` and prefaced with the line `"Traceback for failure in
{descr_name}"`.
You need to pass the `logger` for the current module as a third argument to the
decorator.

This catch-all exception handling makes development more difficult, because for
example a debugger won't be able to stop on an unhandled exception. Therefore,
it is possible to easily disable the exception handling for all functions that
are decorated in this way. This is described in detail here:
:ref:`logging`.

---

### Contributing Devenv Setup (`docs/contributing/devenv_setup.rst`)

.. _installing_for_devs:

=====================================
Setting up FastF1 for development
=====================================

.. _dev-environment:

Creating a dedicated environment
================================
You should set up a dedicated environment to decouple your FastF1
development from other Python and FastF1 installations on your system.
Here we use python's virtual environment `venv`_, but you may also use others
such as conda.

.. _venv: https://docs.python.org/3/library/venv.html

A new environment can be set up with ::

   python -m venv <file folder location>

and activated with one of the following::

   source <file folder location>/bin/activate  # Linux/macOS
   <file folder location>\Scripts\activate.bat  # Windows cmd.exe
   <file folder location>\Scripts\Activate.ps1  # Windows PowerShell

Whenever you plan to work on FastF1, remember to activate the development
environment in your shell.

Retrieving the latest version of the code
=========================================

FastF1 is hosted at https://github.com/theOehrly/Fast-F1.git.

    git clone https://github.com/theOehrly/Fast-F1.git

This will place the sources in a directory :file:`Fast-F1` below your
current working directory.

If you have the proper privileges, you can use ``git@`` instead of
``https://``, which works through the ssh protocol and might be easier to use
if you are using 2-factor authentication.

The data that the tests and the documentation build run against is provided by
two git submodules. Fetch them from within the :file:`Fast-F1` directory, as
needed, using ::

    git submodule update --init --depth 1 fastf1/testing/data   # for the tests
    git submodule update --init --depth 1 docs/data             # for the docs

Each of these downloads roughly 80 MB and uses a few hundred MB of disk space.
See :ref:`testing_test_data` and :ref:`documenting_doc_data` for details.

Installing FastF1 in editable mode
======================================
Install FastF1 in editable mode from the :file:`Fast-F1` directory
using the command ::

    python -m pip install -e .

The 'editable/develop mode', builds everything and places links in your Python
environment so that Python will be able to import FastF1 from your
development source directory. This allows you to import your modified version
of FastF1 without re-installing after every change.

.. _install_pre_commit:

Installing additional dependencies for development
==================================================
To install additional dependencies for development and testing run the
following command within the :file:`Fast-F1` directory::

    python -m pip install -r requirements/dev.txt

If you also want to build the documentation, you need to install further
additional dependencies::

    python -m pip install -r requirements/doc-build.txt


.. _pre_commit_hooks:

Installing pre-commit hooks
===========================
It is recommended to install `pre-commit <https://pre-commit.com/>`_ hooks.
These will automatically check and partially fix code style issues (using the
ruff linter and isort) when you run ``git commit``. The hooks are defined in
the top level ``.pre-commit-config.yaml`` file. To install the hooks ::

    pip install pre-commit
    pre-commit install

---

### Contributing Documenting Fastf1 (`docs/contributing/documenting_fastf1.rst`)

.. _documenting-fastf1:

=====================
Writing documentation
=====================

Getting started
===============

General file structure
----------------------

All documentation is built from the :file:`docs/`.  The :file:`docs/`
directory contains configuration files for Sphinx and reStructuredText
(ReST_; ``.rst``) files that are rendered to documentation pages.


Setting up the doc build
------------------------

The documentation for FastF1 is generated from reStructuredText (ReST_)
using the Sphinx_ documentation generation tool.

To build the documentation you will need to
:ref:`set up FastF1 for development <installing_for_devs>`.

Building the docs
-----------------

The documentation sources are found in the :file:`docs/` directory in the trunk.
The configuration file for Sphinx is :file:`docs/conf.py`. It controls which
directories Sphinx parses, how the docs are built, and how the extensions are
used. The examples in the documentation are built against frozen API responses that
are provided by a git submodule. Fetch it before building the documentation
for the first time (see :ref:`documenting_doc_data`)::

   git submodule update --init --depth 1 docs/data

To build the documentation in html format run the following command
from the :file:`docs/` directory:

.. code:: sh

  make html


The generated documentation can be found in :file:`docs/_build/html` and viewed
in an internet browser by opening the html files. Run the following command
to open the homepage of the documentation build:

.. code:: sh

  make show


.. _documenting_doc_data:

Documentation data
------------------

The documentation build never makes requests to the live APIs. The examples
run against a frozen snapshot of previously recorded API responses instead, so
that the documentation is reproducible and independent of the availability of
the API servers.

This data lives in a separate repository,
`fastf1-doc-data <https://github.com/theOehrly/fastf1-doc-data>`_, which is
included as a git submodule in :file:`docs/data/`. Fetch it before building the
documentation for the first time::

   git submodule update --init --depth 1 docs/data

The commit of the submodule that is referenced by FastF1 is part of every
FastF1 commit. Checking out an older version of FastF1 and updating the
submodule therefore gives you exactly the data that this version of the
documentation was built against. The continuous integration build uses the
same referenced commit.

The directory :file:`doc_cache/` that is created in the root of the repository
is used for FastF1's own parsed-data cache (stage 2 cache) while the
documentation is built. It only serves to improve performance, is not version
controlled and can be deleted at any time.

The tests use a separate dataset, see :ref:`testing_test_data`.


Adding documentation data
.........................

If an example requires data for which no response has been recorded, the build
fails at the very end and reports the affected URLs. This usually means that
the submodule is out of date, so try running
``git submodule update --init --depth 1 docs/data`` first.

If you write an example that requires data which has not been recorded yet,
you need to record it. **Please first check whether you can write your example
based on a session that is already part of the data.** Loading a single
additional race session adds roughly 30 MB of data that everybody who
contributes to FastF1 needs to download.

To record the missing data, run the following command from the :file:`docs/`
directory::

   make record-data

This deletes the stage 2 cache and the previous build output, then builds the
documentation with recording enabled. Only the missing responses are requested
from the API; data that is already available is never re-downloaded. The new
responses are written to :file:`docs/data/http_cache/`, where they show up as
untracked files, and are listed at the end of the build.

.. note::

   Recording requires an IP address that is not blocked by the F1 API. Data
   centre IP addresses are usually blocked, so this cannot be done from a CI
   runner.

Because :file:`docs/data/` is a submodule, these files need to be contributed
to the ``fastf1-doc-data`` repository:

#. Fork `fastf1-doc-data <https://github.com/theOehrly/fastf1-doc-data>`_,
   then commit the new files inside the submodule and push them to your fork::

      cd docs/data
      git status                    # you should be on a branch, not detached
      git checkout -b add-data-<topic>
      git remote add fork git@github.com:<you>/fastf1-doc-data.git
      git status                    # this should list additions only
      git add http_cache
      git commit -m "add documentation data for <session>"
      git push fork add-data-<topic>

   Recording only ever adds files. Any deletion or modification that shows up
   here means that something went wrong, so investigate before committing.
   If the push is rejected with ``shallow update not allowed``, run
   ``git fetch --unshallow origin`` first; the submodule was cloned with
   ``--depth 1``.

   Then open a pull request against ``fastf1-doc-data``.
#. Once it is merged, update the submodule reference in your FastF1 pull
   request, so that the new data is actually used::

      git submodule update --remote docs/data
      git add docs/data

   Data that only exists in a fork or that is newer than the referenced commit
   is never visible to the continuous integration build.

If you are unsure about any of this, just open your FastF1 pull request and
ask. Recording the data can also be done for you.


Writing documentation
---------------------

In general, the style guidelines and formatting conventions described in
https://matplotlib.org/stable/devel/documenting_mpl.html should be applied to
FastF1 as well.

One notable exception is that FastF1 uses the `google docstring standard
<https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html>`_
instead of the numpydoc format.



.. _ReST: https://docutils.sourceforge.io/rst.html
.. _Sphinx: http://www.sphinx-doc.org

---

### Contributing Index (`docs/contributing/index.rst`)

.. _developers-guide-index:

############
Contributing
############

Thank you for your interest in helping to improve FastF1! There are various
ways to contribute to FastF1. All of them are super valuable but don't
necessarily require writing code at all. For example:

- contributing to the documentation
- opening new issues for bugs
- requesting new features
- asking for clarification on things you find unclear
- fixing bugs
- writing example scripts for the gallery


.. raw:: html

   <div style="margin: 2em 0">
     <a href="contributing.html#submitting-a-bug-report"><span class="ff1-button">Report a bug</span></a>
     <a href="contributing.html#request-a-new-feature"><span class="ff1-button">Request a feature</span></a>
     <a href="contributing.html#contributing-code"><span class="ff1-button">Contribute code</span></a>
     <a href="contributing.html#contributing-documentation"><span class="ff1-button">Write documentation</span></a>
   </div>

.. toctree::
   :maxdepth: 2

   contributing.rst
   devenv_setup.rst
   testing.rst
   documenting_fastf1.rst
   coding_guide.rst
   ai_policy.rst


**Acknowledgement**: This contribution guide is heavily based on and in large
parts copied over and adapted from Matplotlibs documentation. There's no need
to reinvent the wheel if others have done a great job of explaining things
already.

---

### Contributing Testing (`docs/contributing/testing.rst`)

.. _testing:

=======
Testing
=======

FastF1 uses the pytest_ framework.

The tests are in :file:`fastf1/tests`, and customizations to the pytest
testing infrastructure are in ``fastf1.testing``.

.. _pytest: http://doc.pytest.org/en/latest/
.. _pytest-xdist: https://pypi.org/project/pytest-xdist/


.. _testing_requirements:

Requirements
------------

To run the tests you will need to
:ref:`set up FastF1 for development <installing_for_devs>`.


Running the tests
-----------------

In the **root directory** of your development repository run::

   python -m pytest


pytest can be configured via a lot of `command-line parameters`_. Some
particularly useful ones are:

=============================  ===========
``-v`` or ``--verbose``        Be more verbose
``-n NUM``                     Run tests in parallel over NUM
                               processes (requires pytest-xdist_)
``--capture=no`` or ``-s``     Do not capture stdout
=============================  ===========

To run a single test from the command line, you can provide a file path,
optionally followed by the function separated by two colons, e.g., (tests do
not need to be installed, but FastF1 should be)::

  pytest fastf1/tests/test_events.py::test_event_get_session_date


In addition, the following FastF1-specific options are available:

===========================  ===========
``--prj-doc``                Run *only* the tests for project structure and
                             documentation
``--create-http-cache``      Record missing test data from the live APIs,
                             see :ref:`testing_test_data`
===========================  ===========


.. _command-line parameters: http://doc.pytest.org/en/latest/usage.html


.. _testing_test_data:

Test data
---------

The tests never make requests to the live APIs. They run against a frozen
snapshot of previously recorded API responses instead, so that test results are
reproducible and independent of the availability of the API servers.

This test data lives in a separate repository,
`fastf1-test-data <https://github.com/theOehrly/fastf1-test-data>`_, which is
included as a git submodule in :file:`fastf1/testing/data/`. Fetch it before
running the tests for the first time::

   git submodule update --init --depth 1 fastf1/testing/data

The submodule contains the recorded API responses in :file:`http_cache/` as
well as the static test files that some tests read directly, namely the
live timing data in :file:`livedata/` and the mocked API responses in
:file:`cache_test/`.

The commit of the submodule that is referenced by FastF1 is part of every
FastF1 commit. Checking out an older version of FastF1 and updating the
submodule therefore gives you exactly the test data that this version was
developed against. The continuous integration tests use the same referenced
commit, so that they test against the same data as a local test run.

The documentation build uses a separate dataset, see
:ref:`documenting_doc_data`.

The directory :file:`test_cache/` that is created in the root of the repository
is used for FastF1's own parsed-data cache (stage 2 cache) while the tests run.
It stores data after parsing in FastF1 and only serves to improve performance.
This directory is not version controlled and can be deleted at any time.


Adding test data
................

If a test fails because no test data is available for a request, pytest will
report the affected URLs at the end of the test run. This usually means that
the submodule is out of date, so try running
``git submodule update --init --depth 1 fastf1/testing/data`` first.

If you write a test that requires data which has not been recorded yet, you
need to record it. **Please first check whether you can write your test based
on a session that is already part of the test data.** Loading a single
additional race session adds roughly 30 MB of data that everybody who
contributes to FastF1 needs to download.

To record the missing data, run the affected tests with::

   python -m pytest --create-http-cache fastf1/tests/test_my_new_test.py

Only the missing responses are requested from the API; data that is already
available is never re-downloaded. The new responses are written to
:file:`fastf1/testing/data/http_cache/`, where they show up as untracked
files.

Because :file:`fastf1/testing/data/` is a submodule, these files need to be
contributed to the ``fastf1-test-data`` repository:

#. Fork `fastf1-test-data <https://github.com/theOehrly/fastf1-test-data>`_,
   then commit the new files inside the submodule and push them to your fork::

      cd fastf1/testing/data
      git status                    # you should be on a branch, not detached
      git checkout -b add-data-<topic>
      git remote add fork git@github.com:<you>/fastf1-test-data.git
      git status                    # this should list additions only
      git add http_cache
      git commit -m "add test data for <session>"
      git push fork add-data-<topic>

   Recording only ever adds files. Any deletion or modification that shows up
   here means that something went wrong, so investigate before committing.
   If the push is rejected with ``shallow update not allowed``, run
   ``git fetch --unshallow origin`` first; the submodule was cloned with
   ``--depth 1``.

   Then open a pull request against ``fastf1-test-data``.
#. Once it is merged, update the submodule reference in your FastF1 pull
   request, so that the new data is actually used::

      git submodule update --remote fastf1/testing/data
      git add fastf1/testing/data

   Data that only exists in a fork or that is newer than the referenced commit
   is never visible to the continuous integration tests.

If you are unsure about any of this, just open your FastF1 pull request and
ask. Recording the data can also be done for you.


Linting - Code style tests
--------------------------

FastF1 uses Ruff_ and isort_ to ensure that the code has a consistent style and
is easily readable. All code should conform to the guidelines that are defined
by PEP8_.

To check whether your code is formatted correctly, run::

  ruff check .


To check and correct the import order, run::

  python -m isort .

If you have installed the :ref:`pre-commit hooks <pre_commit_hooks>`,
these commands will also be run automatically before each commit.


.. _Ruff: https://docs.astral.sh/ruff/
.. _isort: https://pycqa.github.io/isort/
.. _PEP8: https://pep8.org/


Github Actions CI Tests
-----------------------

FastF1 uses Github Actions to run the tests on every push to the repository and
when updating a pull request. Usually, you should just let all tests run and
make sure that they are passing.

In rare cases, it may be useful to skip some tests. You can do this by adding
a specific comment to the commit message. The following comments are supported:

- ``[skip-pytest]``: Skip pytest runs on all Python versions
- ``[skip-ruff]``: Skip Ruff code style checks
- ``[skip-isort]``: Skip isort import order checks
- ``[skip-doc-build]``: Skip building the documentation
- ``[skip-readme-test]``: Skip the README render test for PyPI

---

### Data Reference Howto Accurate Calculations (`docs/data_reference/howto_accurate_calculations.rst`)

.. _howto_accurate_calculations:

======================================
How to perform calculations accurately
======================================

This is intended to be a writeup of my experiences. I discovered all of this when trying to implement new functionality
or when trying to improve existing calculations. The data that can be received from the F1 API has a very limited
sample rate of about 4-5 Hz. Furthermore, the data is somewhat jittery. That said, one can still perform accurate
calculations based on this data. But doing validation and accuracy checks is a must.


Validating results
------------------

It is extremely important to never assume that something is correct just because it looks right on the first glance.
Often it is possible to validate the data "against itself" or just validate it logically. This may not always give
absolute certainty that the results are accurate. But it can show when there are errors in the calculations. Or maybe
the data is simply not accurate enough for what one is trying to do.

Here are two examples for (partially) validating calculated data:

    - Use a known accurate value as a comparison. Let's assume we calculate the start time of each lap. As a result of
        the calculations we get a timestamp per lap which marks the beginning of this lap. We can now subtract the
        beginnings of two subsequent laps which will give us a measure for how long the first lap was, i.e. the lap
        time. Lap timing is of course also measured separately and known to be accurate to one millisecond. And it
        should be the same as our calculated values. This way we can validate the integrity of the calculated
        timestamps, excluding any random errors or general inaccuracy. Of course, a fixed offset which is equal for all
        timestamps would not show up as an error when using this validation.

    - Check that the data makes sense. Again, assume we are trying to find the start of a lap. If have calculated the
        timestamps for that, we can also calculated the position of the car at this time. Every time a lap starts, the
        car should be crossing over the finish line. And the finish line cannot physically move. So the position of the
        car should be the same every time a new lap starts. If it isn't there has to be an error somewhere.



Working with the available data
-------------------------------

A few straight forward guidelines can be set.

    - Do not work with interpolated values. Interpolation does always introduce some inaccuracy and in my experience
        this is rarely offset by more data points or by the fact that a timestamp matches better.

        The API provides car data and position data separately and with two different time bases. If somehow possible,
        you should use the data with the existing time base. That means, you cannot merge the datasets for use in
        calculations as this requires interpolation. If you need a combined end result and/or a different time base,
        do only merge and resample the result of your calculations. Do not resample the input data.

    - Do not perform calculations based on values that have been calculated by means of integration. The low sample rate
        of the source data and the existing inaccuracies mean that integration will always be error prone. Errors can
        stack up and single outliers will influence all further results of the integration.

Clearly, this rules can not always be followed. They sometimes need to be broken as there may be no other way around it.
But, by keeping these rules in mind, potential error sources can be reduced.



Slicing data by lap for use in further calculations
----------------------------------------------------

If you simply wish to visualize existing data, slicing laps is rather straight forward.

.. code-block:: python

    session = fastf1.get_session(2020, 4, 'Q')
    session.load()
    fastest_lap = session.laps.pick_fastest()
    tel = fastest_lap.telemetry

This will give you the merged telemetry with a first and last value being interpolated additionally so as to exactly
match the start and end of the lap.
This data is not suitable for further calculations though.

If you want to perform your own calculations with the data, you should use the raw data.
To stay away from interpolation before doing any calculations, the following could be done:

.. code-block:: python

    session = fastf1.get_session(2020, 4, 'Q')
    session.load()
    fastest_lap = session.laps.pick_fastest()

    # use padding so that there are values outside of the desired range for accurate interpolation later
    car_data = fastest_lap.get_car_data(pad=1, pad_side='both')
    pos_data = fastest_lap.get_pos_data(pad=1, pad_side='both')

    # do calculations here
    # ...
    # ...

    merged_data = car_data.merge_channels(pos_data)

    # slice again to remove the padding and interpolate the exact first and last value
    merged_data = merged_data.slice_by_lap(fastest_lap, interpolate_edges=True)



Disclaimer
----------

The information here is what I have discovered to be most effective. This is probably not perfect. There are just too
many (time consuming) things that can be tried out. If you have some better ideas or want to discuss accuracy and
possibilities, feel free to open an issue about it.

---

### Data Reference Index (`docs/data_reference/index.rst`)

**************
Data Reference
**************


.. warning::

  The data reference is still under construction and currently only provides limited
  information.


The data reference provides an overview of all the data that is available via FastF1.


.. toctree::
   :maxdepth: 1
   :caption: Additional Information

   howto_accurate_calculations
   time_explanation


==============
Available Data
==============

The following is a short overview over the available data with some references
to functions and objects used to work with this data.

In most cases, the default workflow with FastF1 is to create a
:class:`~fastf1.core.Session` object using :func:`~fastf1.get_session`. You,
will then access all data through the session object. One notable exception to
this pattern is the wrapper for Ergast.

.. table:: Overview over the available data
   :widths: auto

   =====================  ==============================================================================================================================  ==================================================================================================
   Topic                  Data                                                                                                                            References
   =====================  ==============================================================================================================================  ==================================================================================================
   Event Schedule         event names, countries, locations, dates, scheduled starting times,... (previous and current season including upcoming events)  :ref:`event-schedule` :func:`~fastf1.get_event_schedule` :func:`~fastf1.get_event`
   Results                driver names, team names, finishing and grid positions, points, finishing status,...                                            :class:`~fastf1.core.SessionResults`, :class:`~fastf1.core.DriverResult`
   Timing Data            sector times, lap times, pit stops, tyre data and much more                                                                     :attr:`~fastf1.core.Session.laps` :class:`~fastf1.core.Laps`
   Track Status           flags, safety car                                                                                                               :attr:`~fastf1.core.Session.track_status`
   Session Status         started, finished, finalized                                                                                                    :attr:`~fastf1.core.Session.session_status`
   Race Control Messages  investigations, penalties, restart announcements,...                                                                            :attr:`~fastf1.core.Session.race_control_messages`
   Telemetry              speed, rpm, gear, normalized track position, ...                                                                                :class:`~fastf1.core.Telemetry` :func:`~fastf1.core.Lap.get_car_data`
   Track Markers          corner numbers, marshall sectors, marshall lights                                                                               :func:`~fastf1.core.Session.get_circuit_info`, :ref:`circuit_info`
   Jolpica-F1 API         all endpoints that are provided by Jolpica-F1 (previously Ergast)                                                               :ref:`jolpica`
   =====================  ==============================================================================================================================  ==================================================================================================


Compatibility and Availability
------------------------------

Timing data, session information, car telemetry and position data are available
from 2018 onwards. (This data is usually available within 30-120 minutes after
the end of a session.)
It is also possible to obtain this data by recording the data live stream,
using the live timing recorder that is built into FastF1. Usually this is not
necessary but there have been server issues in the past which caused the
data to be not available for download. Recording of the data live stream is
therefore mostly a solution for redundancy.

Schedule information and session results are available for older seasons as
well, going back as far as 1950 (limited to data that is available through
`Ergast <https://ergast.com/mrd/>`_).

---

### Data Reference Time Explanation (`docs/data_reference/time_explanation.rst`)

.. _time-explanation:

===================================
Time, Date and Timing - Explanation
===================================

Working with Formula 1 data (or any motorsport data for that matter) requires working working with lots of different
values of time. These values can denote a point in time or a duration. The following is an explanation of the different
values of time which are used in this module.


Points in Time
--------------

Three different values of time can denote a point in time in this module. These are:
  - Time
  - SessionTime
  - Date

`SessionTime` is a time which has a more or less arbitrary zero point multiple minutes before a session officially starts.
It is directly provided by the F1 live timing api. SessionTime zero marks the beginning of all data streams. The
SessionTime references events within the boundaries of one session.

  --> SessionTime is relative to the beginning of a session

`Date` is a UTC timestamp containing date and time. It is therefore an absolute reference to tell when something
happened in the context of the time of day.

  --> Date is an absolute point in time

`Time` references data relative in the current data set. The first sample of a given set of data will always mark the
zero point for this set of data.

  --> Time is relative to the first sample of data in a set of data


For a sample of telemetry data this means, that the sample will always have the same value for its `Date` and
`SessionTime`. But its value for `Time` will change when the dataset is modified.

Take the following set of example telemetry. Lets assume the variable `tel` holds previously loaded telemetry data
for one driver an for a full session (only time data is shown for simplification).

.. doctest::
  :hide:

  >>> import fastf1
  >>> import pandas
  >>> session = fastf1.get_session(2020, 8, 'R')
  >>> session.load()

.. doctest::

  >>> tel = session.car_data['33'].loc[:, ['Time', 'SessionTime', 'Date']]
  >>> tel
                          Time            SessionTime                    Date
  0     0 days 00:00:02.984000 0 days 00:00:02.984000 2020-09-06 12:40:03.180
  1     0 days 00:00:03.224000 0 days 00:00:03.224000 2020-09-06 12:40:03.420
  2     0 days 00:00:03.464000 0 days 00:00:03.464000 2020-09-06 12:40:03.660
  3     0 days 00:00:03.704000 0 days 00:00:03.704000 2020-09-06 12:40:03.900
  4     0 days 00:00:03.944000 0 days 00:00:03.944000 2020-09-06 12:40:04.140
  ...                      ...                    ...                     ...
  35533 0 days 02:23:27.764000 0 days 02:23:27.764000 2020-09-06 15:03:27.960
  35534 0 days 02:23:28.004000 0 days 02:23:28.004000 2020-09-06 15:03:28.200
  35535 0 days 02:23:28.244000 0 days 02:23:28.244000 2020-09-06 15:03:28.440
  35536 0 days 02:23:28.484000 0 days 02:23:28.484000 2020-09-06 15:03:28.680
  35537 0 days 02:23:28.724000 0 days 02:23:28.724000 2020-09-06 15:03:28.920
  <BLANKLINE>
  [35538 rows x 3 columns]

The telemetry comprises approximately 2 hours and 23 minutes of data.
The session (a race in this case) did not last this long, but the data starts
before the beginning of the session and ends after the end.
`SessionTime` and `Time` are exactly the same for this set of data.
This is how the data looks as it is created by the api functions.
Next, the data is sliced to only include a subset of the full session.

.. doctest::

  >>> t1 = pandas.Timedelta(hours=1, minutes=20)
  >>> t2 = pandas.Timedelta(hours=1, minutes=30)
  >>> tel.slice_by_time(t1, t2)
                          Time            SessionTime                    Date
  19811 0 days 00:00:00.195000 0 days 01:20:00.195000 2020-09-06 14:00:00.391
  19812 0 days 00:00:00.435000 0 days 01:20:00.435000 2020-09-06 14:00:00.631
  19813 0 days 00:00:00.676000 0 days 01:20:00.676000 2020-09-06 14:00:00.872
  19814 0 days 00:00:00.916000 0 days 01:20:00.916000 2020-09-06 14:00:01.112
  19815 0 days 00:00:01.156000 0 days 01:20:01.156000 2020-09-06 14:00:01.352
  ...                      ...                    ...                     ...
  22288 0 days 00:09:59.076000 0 days 01:29:59.076000 2020-09-06 14:09:59.272
  22289 0 days 00:09:59.277000 0 days 01:29:59.277000 2020-09-06 14:09:59.473
  22290 0 days 00:09:59.517000 0 days 01:29:59.517000 2020-09-06 14:09:59.713
  22291 0 days 00:09:59.757000 0 days 01:29:59.757000 2020-09-06 14:09:59.953
  22292 0 days 00:09:59.997000 0 days 01:29:59.997000 2020-09-06 14:10:00.193
  <BLANKLINE>
  [2482 rows x 3 columns]

`SessionTime` and `Date` have kept there reference point. But the reference point for `Time` has changed and its new
zero is now the first sample of this set of data.
If this subset of data was sliced again, `Time` would change again so as to start at zero on the first sample.

All three of these values have a use for different reasons. Here are some examples.

To check which other cars are on track while one driver is on a fast lap `SessionTime` is useful.

When overlapping multiple laps for comparison the data can be plotted over `Time` so that different laps have
a common zero point.

`Date` is useful when checking out something in reference to commonly used human time.

The relation between `SessionTime` and `Date` is a constant offset. This value is available through the session class.

.. doctest::

  >>> session.t0_date
  Timestamp('2020-09-06 12:40:00.196000')

As already mentioned above, the zero point of the session time is before the actual start of a session. The session
itself officially starts at some later point in time. This value is also available through the session class.

.. doctest::

  >>> session.session_start_time
  datetime.timedelta(seconds=2008, microseconds=79000)
  >>> str(session.session_start_time)
  '0:33:28.079000'



Lap timing
----------

.. currentmodule:: fastf1.core

Lap timing data is available in an instance of :class:`Laps` in :attr:`Session.laps`.
For each lap, the usual official timing information is available. It consists of the lap time and the sector times.
The columns for this data in :class:`Laps` are called 'LapTime', 'Sector1Time', 'Sector2Time' and 'Sector3Time'.
These four values are highly accurate and are considered the absolute truth.

For each lap, additional data is available. Amongst others the following time related data:
  - 'Time': This marks the point in time when a lap was set, i.e. finished, as a SessionTime. The name 'Time' is
    confusing here as it should be 'SessionTime'. It is kept mainly for backwards compatibility.
  - 'Sector*SessionTime': For each sector a session time is available. This marks the point in time when a sector time
    was set. The 'Sector3Session' time is mathematically the same as the end of the lap ('Time'). In most cases this is
    true, but there can be minor deviations in some edge cases. (In some cases the api function can not calculate the
    timestamps correctly.)
  - 'LapStartTime': This marks the point in time (SessionTime) when a lap was started and is equivalent to the 'Time'
    and 'Sector3Time' of the previous lap.
  - 'LapStartDate': This is the same as 'LapStartTime' just expressed as 'Date' instead of 'SessionTime'
  - 'PitInTime'/'PitOutTime': This marks the point in time (SessionTime) when a car entered or left the pits.

These additional timestamps are not provided by the api. They are calculated as accurate as possible from the available
data but the accuracy can not be verified to millisecond precision.

---

### Getting Started Basics (`docs/getting_started/basics.rst`)

Getting Started with the Basics
===============================

FastF1 is built mainly around Pandas DataFrame and Series objects.
If you are familiar with Pandas you'll immediately recognize this and working
with the data will be fairly straightforward. (If you're
not familiar with Pandas at all, it might be helpful to check out a short
tutorial.)


Loading a session or an event
------------------------------

The :class:`fastf1.core.Session` object is an important starting point for
everything you do with FastF1. Usually, the first thing you want to do
is load a session. For this, you should use
:func:`fastf1.get_session`.

For example, let's load the Qualifying of the 7th race of the 2021 season:

.. doctest::

  >>> import fastf1
  >>> session = fastf1.get_session(2021, 7, 'Q')
  >>> session.name
  'Qualifying'
  >>> session.date
  Timestamp('2021-06-19 13:00:00')


Now, which race weekend are we actually looking at here?
For this we have the :class:`~fastf1.events.Event` object which holds
information about each event. An event can be a race weekend or a testing
event and usually consists of multiple sessions. It is accessible through the
session object.

.. doctest::

  >>> session.event
  RoundNumber                                                     7
  Country                                                    France
  Location                                             Le Castellet
  OfficialEventName    FORMULA 1 EMIRATES GRAND PRIX DE FRANCE 2021
  EventDate                                     2021-06-20 00:00:00
  EventName                                       French Grand Prix
  EventFormat                                          conventional
  Session1                                               Practice 1
  Session1Date                            2021-06-18 11:30:00+02:00
  Session1DateUtc                               2021-06-18 09:30:00
  Session2                                               Practice 2
  Session2Date                            2021-06-18 15:00:00+02:00
  Session2DateUtc                               2021-06-18 13:00:00
  Session3                                               Practice 3
  Session3Date                            2021-06-19 12:00:00+02:00
  Session3DateUtc                               2021-06-19 10:00:00
  Session4                                               Qualifying
  Session4Date                            2021-06-19 15:00:00+02:00
  Session4DateUtc                               2021-06-19 13:00:00
  Session5                                                     Race
  Session5Date                            2021-06-20 15:00:00+02:00
  Session5DateUtc                               2021-06-20 13:00:00
  F1ApiSupport                                                 True
  Name: 7, dtype: object

The :class:`~fastf1.events.Event` object is a subclass of a
:class:`pandas.Series`. The individual values can therefore be accessed as it
is common for pandas objects:

.. doctest::

  >>> session.event['EventName']
  'French Grand Prix'
  >>> session.event['EventDate']  # this is the date of the race day
  Timestamp('2021-06-20 00:00:00')

You can also load an event directly, by using the function
:func:`fastf1.get_event`. The :class:`~fastf1.events.Event` object in turn
provides methods for accessing the individual associated sessions.

.. doctest::

  >>> event = fastf1.get_event(2021, 7)
  >>> event
  RoundNumber                                                     7
  Country                                                    France
  Location                                             Le Castellet
  OfficialEventName    FORMULA 1 EMIRATES GRAND PRIX DE FRANCE 2021
  EventDate                                     2021-06-20 00:00:00
  EventName                                       French Grand Prix
  EventFormat                                          conventional
  Session1                                               Practice 1
  Session1Date                            2021-06-18 11:30:00+02:00
  Session1DateUtc                               2021-06-18 09:30:00
  Session2                                               Practice 2
  Session2Date                            2021-06-18 15:00:00+02:00
  Session2DateUtc                               2021-06-18 13:00:00
  Session3                                               Practice 3
  Session3Date                            2021-06-19 12:00:00+02:00
  Session3DateUtc                               2021-06-19 10:00:00
  Session4                                               Qualifying
  Session4Date                            2021-06-19 15:00:00+02:00
  Session4DateUtc                               2021-06-19 13:00:00
  Session5                                                     Race
  Session5Date                            2021-06-20 15:00:00+02:00
  Session5DateUtc                               2021-06-20 13:00:00
  F1ApiSupport                                                 True
  Name: 7, dtype: object
  >>> session = event.get_race()
  >>> session.name
  'Race'


Loading a session or an event by name
--------------------------------------

As an alternative to specifying an event number you can also load
events by using a clearly identifying name.

.. doctest::

  >>> event = fastf1.get_event(2021, 'French Grand Prix')
  >>> event['EventName']
  'French Grand Prix'

You do not need to provide the exact event name. FastF1 will return the
event (or session) that matches your provided name best. Even if you don't
specify the correct name chances are high that FastF1 will find the event
you are looking for.

  >>> event = fastf1.get_event(2021, 'Spain')
  >>> event['EventName']
  'Spanish Grand Prix'

But be aware that this does not always work. Sometimes another name just
matches the provided string better. For example, what we actually want is the
'Emilia Romagna Grand Prix' but we get the 'Belgian Grand Prix' if we don't
specify the name fully and/or correct enough. Why? Because FastF1 is not a
proper intelligent search engine. So check your results.

  >>> event = fastf1.get_event(2021, 'Emilian')
  >>> event['EventName']
  'Belgian Grand Prix'

We need to be a bit more precise here.

  >>> event = fastf1.get_event(2021, 'Emilia Romagna')
  >>> event['EventName']
  'Emilia Romagna Grand Prix'

Events and sessions can also be loaded by their country or location.

  >>> session = fastf1.get_session(2021, 'Silverstone', 'Q')
  >>> session.event['EventName']
  'British Grand Prix'


Working with the event schedule
-------------------------------

Instead of loading a specific session or event, it is possible to load the
full event schedule for a season. The :class:`~fastf1.events.EventSchedule`
is a subclass of a :class:`pandas.DataFrame`. Detailed information about
the data that is available in the event schedule can be found in
:ref:`event-schedule`.

  >>> schedule = fastf1.get_event_schedule(2021)
  >>> schedule
      RoundNumber        Country  ...     Session5DateUtc F1ApiSupport
  0             0        Bahrain  ...                 NaT        False
  1             1        Bahrain  ... 2021-03-28 15:00:00         True
  2             2          Italy  ... 2021-04-18 13:00:00         True
  3             3       Portugal  ... 2021-05-02 14:00:00         True
  4             4          Spain  ... 2021-05-09 13:00:00         True
  5             5         Monaco  ... 2021-05-23 13:00:00         True
  6             6     Azerbaijan  ... 2021-06-06 12:00:00         True
  7             7         France  ... 2021-06-20 13:00:00         True
  8             8        Austria  ... 2021-06-27 13:00:00         True
  9             9        Austria  ... 2021-07-04 13:00:00         True
  10           10  Great Britain  ... 2021-07-18 14:00:00         True
  11           11        Hungary  ... 2021-08-01 13:00:00         True
  12           12        Belgium  ... 2021-08-29 13:00:00         True
  13           13    Netherlands  ... 2021-09-05 13:00:00         True
  14           14          Italy  ... 2021-09-12 13:00:00         True
  15           15         Russia  ... 2021-09-26 12:00:00         True
  16           16         Turkey  ... 2021-10-10 12:00:00         True
  17           17  United States  ... 2021-10-24 19:00:00         True
  18           18         Mexico  ... 2021-11-07 19:00:00         True
  19           19         Brazil  ... 2021-11-14 17:00:00         True
  20           20          Qatar  ... 2021-11-21 14:00:00         True
  21           21   Saudi Arabia  ... 2021-12-05 17:30:00         True
  22           22      Abu Dhabi  ... 2021-12-12 13:00:00         True
  <BLANKLINE>
  [23 rows x 23 columns]
  >>> schedule.columns  # doctest: +NORMALIZE_WHITESPACE
  Index(['RoundNumber', 'Country', 'Location', 'OfficialEventName', 'EventDate',
         'EventName', 'EventFormat', 'Session1', 'Session1Date',
         'Session1DateUtc', 'Session2', 'Session2Date', 'Session2DateUtc',
         'Session3', 'Session3Date', 'Session3DateUtc', 'Session4',
         'Session4Date', 'Session4DateUtc', 'Session5', 'Session5Date',
         'Session5DateUtc', 'F1ApiSupport'],
        dtype='object')

The event schedule provides methods for selecting specific events:

  >>> gp_12 = schedule.get_event_by_round(12)
  >>> gp_12['Country']
  'Belgium'
  >>> gp_austin = schedule.get_event_by_name('Austin')
  >>> gp_austin['Country']
  'United States'


Displaying driver info and session results
------------------------------------------

We have created a session now but everything has been rather boring so far.
So let's make it a bit more interesting by taking a look at the results of
this session. For this, it is first necessary to call
:func:`Session.load <fastf1.core.Session.load>`. This will load all available data for the
session from various APIs. Downloading and processing of the data may take a
few seconds. It is highly recommended to utilize FastF1's built-in caching
functionality to speed up data loading and prevent excessive API requests.

  >>> session = fastf1.get_session(2021, 'French Grand Prix', 'Q')
  >>> session.load()
  >>> session.results
     DriverNumber BroadcastName Abbreviation  ... Status Points Laps
  33           33  M VERSTAPPEN          VER  ...           NaN  NaN
  44           44    L HAMILTON          HAM  ...           NaN  NaN
  77           77      V BOTTAS          BOT  ...           NaN  NaN
  11           11       S PEREZ          PER  ...           NaN  NaN
  55           55       C SAINZ          SAI  ...           NaN  NaN
  10           10       P GASLY          GAS  ...           NaN  NaN
  16           16     C LECLERC          LEC  ...           NaN  NaN
  4             4      L NORRIS          NOR  ...           NaN  NaN
  14           14      F ALONSO          ALO  ...           NaN  NaN
  3             3   D RICCIARDO          RIC  ...           NaN  NaN
  31           31        E OCON          OCO  ...           NaN  NaN
  5             5      S VETTEL          VET  ...           NaN  NaN
  99           99  A GIOVINAZZI          GIO  ...           NaN  NaN
  63           63     G RUSSELL          RUS  ...           NaN  NaN
  47           47  M SCHUMACHER          MSC  ...           NaN  NaN
  6             6      N LATIFI          LAT  ...           NaN  NaN
  7             7   K RAIKKONEN          RAI  ...           NaN  NaN
  9             9     N MAZEPIN          MAZ  ...           NaN  NaN
  18           18      L STROLL          STR  ...           NaN  NaN
  22           22     Y TSUNODA          TSU  ...           NaN  NaN
  <BLANKLINE>
  [20 rows x 22 columns]

The results object (:class:`fastf1.core.SessionResults`) is a subclass of a
:class:`pandas.DataFrame`. Therefore, we can take a look at what data columns
there are:

  >>> session.results.columns  # doctest: +NORMALIZE_WHITESPACE
  Index(['DriverNumber', 'BroadcastName', 'Abbreviation', 'DriverId', 'TeamName',
         'TeamColor', 'TeamId', 'FirstName', 'LastName', 'FullName',
         'HeadshotUrl', 'CountryCode', 'Position', 'ClassifiedPosition',
         'GridPosition', 'Q1', 'Q2', 'Q3', 'Time', 'Status', 'Points', 'Laps'],
        dtype='object')

As an example, let's display the top ten drivers and their
respective Q3 times. The results are sorted by finishing position, therefore,
this is easy.

  >>> session.results.iloc[0:10].loc[:, ['Abbreviation', 'Q3']]
     Abbreviation                     Q3
  33          VER 0 days 00:01:29.990000
  44          HAM 0 days 00:01:30.248000
  77          BOT 0 days 00:01:30.376000
  11          PER 0 days 00:01:30.445000
  55          SAI 0 days 00:01:30.840000
  10          GAS 0 days 00:01:30.868000
  16          LEC 0 days 00:01:30.987000
  4           NOR 0 days 00:01:31.252000
  14          ALO 0 days 00:01:31.340000
  3           RIC 0 days 00:01:31.382000


Working with laps and lap times
-------------------------------

All individual laps of a session can be accessed through the property
:attr:`Session.laps <fastf1.core.Session.laps>`. The laps are represented 
as :class:`~fastf1.core.Laps` object which again is a subclass of a
:class:`pandas.DataFrame`.

  >>> session = fastf1.get_session(2021, 'French Grand Prix', 'Q')
  >>> session.load()
  >>> session.laps
                        Time Driver  ... FastF1Generated IsAccurate
  0   0 days 00:17:35.479000    GAS  ...           False      False
  1   0 days 00:27:42.702000    GAS  ...           False      False
  2   0 days 00:30:15.038000    GAS  ...           False      False
  3   0 days 00:31:46.936000    GAS  ...           False       True
  4   0 days 00:34:20.695000    GAS  ...           False      False
  ..                     ...    ...  ...             ...        ...
  265 0 days 00:54:22.881000    GIO  ...           False       True
  266 0 days 01:00:32.369000    GIO  ...           False      False
  267 0 days 01:03:24.940000    GIO  ...           False      False
  268 0 days 01:04:56.753000    GIO  ...           False       True
  269 0 days 01:06:42.885000    GIO  ...           False      False
  <BLANKLINE>
  [270 rows x 31 columns]

That's more than 250 laps right there and 26 columns of information.

The following data columns are available:

  >>> session.laps.columns  # doctest: +NORMALIZE_WHITESPACE
  Index(['Time', 'Driver', 'DriverNumber', 'LapTime', 'LapNumber', 'Stint',
         'PitOutTime', 'PitInTime', 'Sector1Time', 'Sector2Time', 'Sector3Time',
         'Sector1SessionTime', 'Sector2SessionTime', 'Sector3SessionTime',
         'SpeedI1', 'SpeedI2', 'SpeedFL', 'SpeedST', 'IsPersonalBest',
         'Compound', 'TyreLife', 'FreshTyre', 'Team', 'LapStartTime',
         'LapStartDate', 'TrackStatus', 'Position', 'Deleted', 'DeletedReason',
         'FastF1Generated', 'IsAccurate'],
        dtype='object')

A detailed explanation for all these columns can be found in the
documentation of the :class:`~fastf1.core.Laps` class.

The :class:`~fastf1.core.Laps` object is not a simple DataFrame though.
Like FastF1's other data objects, it provides some more features specifically
for working with Formula 1 data.

One of these additional features are methods for selecting specific laps.
So let's see what the fastest lap time was and who is on pole.

  >>> fastest_lap = session.laps.pick_fastest()
  >>> fastest_lap['LapTime']
  Timedelta('0 days 00:01:29.990000')
  >>> fastest_lap['Driver']
  'VER'


Check out this example that shows how you can plot lap times:
:ref:`sphx_glr_gen_modules_examples_gallery_results_strategy_plot_qualifying_results.py`

---

### Getting Started Index (`docs/getting_started/index.rst`)

***************
Getting Started
***************


This section provides information on how to install FastF1 and quickly introduces its basic usage.

.. toctree::
    :maxdepth: 1

    installation
    basics

---

### Getting Started Installation (`docs/getting_started/installation.rst`)

Installation
============

FastF1 requires Python |min_python_version| or higher.
It is recommended to install FastF1 using `pip`:

.. code-block:: bash

   pip install fastf1

You can also install using `conda`:

.. code-block:: bash

  conda install -c conda-forge fastf1

Alternatively, a wheel or a source distribution can be downloaded from `PyPI <https://pypi.org/project/fastf1/>`_.

**Installation in Pyodide, JupyterLite and other WASM-based environments**

FastF1 should be mostly compatible with Pyodide and other WASM-based
environments, although this is not extensively tested. Currently, the
installation and usage require some additional steps. You can find more
information and a guide in
`this external repository <https://github.com/f1datajunkie/jupyterlite-fastf1>`_
and the discussion in `this issue <https://github.com/theOehrly/Fast-F1/issues/667>`_.

---

### Api Reference Legacy F1 Api (`docs/api_reference/legacy/f1_api.rst`)

F1 API - :mod:`fastf1.api`
--------------------------

Functions
^^^^^^^^^

.. automodule:: fastf1.api
   :members: pages, make_path, timing_data, timing_app_data, car_data, position_data, track_status_data, session_status_data, race_control_messages, lap_count, driver_info, weather_data, season_schedule, fetch_page, parse

---

### Api Reference Legacy Legacy (`docs/api_reference/legacy/legacy.rst`)

Legacy Functionality - :mod:`fastf1.legacy`
===========================================

.. automodule:: fastf1.legacy
    :members:
    :undoc-members:
    :show-inheritance:

---

--- METRICS ---
- Files Extracted: 79
- Estimated Token Budget: ~49336 tokens
- Canonical Reference: https://codewiki.google/github.com/theOehrly/Fast-F1
