Skip to main content
Visualizing speed variations around a circuit helps identify braking zones, acceleration areas, and flat-out sections. This tutorial shows how to create a color-coded track map where speed is represented by color intensity along the racing line. Multi-driver speed comparison showing speed variations around the circuit

Setup and configuration

First, set up the plotting environment with FastF1 color scheme and configure the session details.
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.collections import LineCollection
import tif1

# Setup plotting with FastF1 colors
tif1.plotting.setup_mpl(color_scheme='fastf1')

# Configuration
year = 2023
event = "Bahrain"
session_type = "Q"
driver = "VER"
colormap = mpl.cm.plasma

Loading session and telemetry

Load the session and extract telemetry data from the driver’s fastest lap.
# Load session
session = tif1.get_session(year, event, session_type)
weekend = session.event

# Get fastest lap telemetry
lap = session.laps.pick_driver(driver).pick_fastest()
telemetry = lap.get_car_data()

# Extract data for plotting
x = telemetry['X'].values
y = telemetry['Y'].values
color = telemetry['Speed'].values

Creating line segments

Convert the track coordinates into line segments for color mapping.
# Create line segments for coloring
points = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)

Building the visualization

Create the plot with a background track line and color-coded speed overlay.
# Create visualization with FastF1 styling
fig, ax = plt.subplots(sharex=True, sharey=True, figsize=(12, 6.75))
fig.suptitle(f'{weekend["EventName"]} {year} - {driver} - Speed',
             size=24, y=0.97, color='white')

# Adjust margins and turn off axis
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.12)
ax.axis('off')
ax.set_aspect('equal', adjustable='datalim')

# Create background track line
ax.plot(x, y, color='black', linestyle='-', linewidth=16, zorder=0)

# Create a continuous norm to map from data points to colors
norm = plt.Normalize(color.min(), color.max())
lc = LineCollection(segments, cmap=colormap, norm=norm,
                   linestyle='-', linewidth=5)

# Set the values used for colormapping
lc.set_array(color)

# Add line segments to plot
line = ax.add_collection(lc)

Adding the color bar

Add a horizontal color bar to show the speed scale.
# Create color bar as legend
cbaxes = fig.add_axes([0.25, 0.05, 0.5, 0.05])
normlegend = mpl.colors.Normalize(vmin=color.min(), vmax=color.max())
legend = mpl.colorbar.ColorbarBase(cbaxes, norm=normlegend,
                                   cmap=colormap, orientation="horizontal")
legend.set_label('Speed (km/h)', color='white', fontsize=12)
legend.ax.xaxis.set_tick_params(color='white')
plt.setp(plt.getp(legend.ax.axes, 'xticklabels'), color='white')

plt.show()

Complete example

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.collections import LineCollection
import tif1

# Setup plotting with FastF1 colors
tif1.plotting.setup_mpl(color_scheme='fastf1')

# Configuration
year = 2023
event = "Bahrain"
session_type = "Q"
driver = "VER"
colormap = mpl.cm.plasma

# Load session
session = tif1.get_session(year, event, session_type)
weekend = session.event

# Get fastest lap telemetry
lap = session.laps.pick_driver(driver).pick_fastest()
telemetry = lap.get_car_data()

# Extract data for plotting
x = telemetry['X'].values
y = telemetry['Y'].values
color = telemetry['Speed'].values

# Create line segments for coloring
points = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)

# Create visualization with FastF1 styling
fig, ax = plt.subplots(sharex=True, sharey=True, figsize=(12, 6.75))
fig.suptitle(f'{weekend["EventName"]} {year} - {driver} - Speed',
             size=24, y=0.97, color='white')

# Adjust margins and turn off axis
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.12)
ax.axis('off')
ax.set_aspect('equal', adjustable='datalim')

# Create background track line
ax.plot(x, y, color='black', linestyle='-', linewidth=16, zorder=0)

# Create a continuous norm to map from data points to colors
norm = plt.Normalize(color.min(), color.max())
lc = LineCollection(segments, cmap=colormap, norm=norm,
                   linestyle='-', linewidth=5)

# Set the values used for colormapping
lc.set_array(color)

# Add line segments to plot
line = ax.add_collection(lc)

# Create color bar as legend
cbaxes = fig.add_axes([0.25, 0.05, 0.5, 0.05])
normlegend = mpl.colors.Normalize(vmin=color.min(), vmax=color.max())
legend = mpl.colorbar.ColorbarBase(cbaxes, norm=normlegend,
                                   cmap=colormap, orientation="horizontal")
legend.set_label('Speed (km/h)', color='white', fontsize=12)
legend.ax.xaxis.set_tick_params(color='white')
plt.setp(plt.getp(legend.ax.axes, 'xticklabels'), color='white')

plt.show()

Interpreting the visualization

  • Red/yellow sections: High-speed areas like straights and fast corners
  • Blue/purple sections: Low-speed areas indicating braking zones and slow corners
  • Color transitions: Show acceleration and deceleration patterns
  • Track layout: Black background line provides context for the circuit shape

Comparing multiple drivers

To compare multiple drivers, create separate plots or overlay them with different colormaps:
drivers = ['VER', 'PER', 'LEC']
fig, axes = plt.subplots(1, len(drivers), figsize=(18, 6))

for idx, driver in enumerate(drivers):
    lap = session.laps.pick_driver(driver).pick_fastest()
    telemetry = lap.get_car_data()

    x = telemetry['X'].values
    y = telemetry['Y'].values
    speed = telemetry['Speed'].values

    points = np.array([x, y]).T.reshape(-1, 1, 2)
    segments = np.concatenate([points[:-1], points[1:]], axis=1)

    axes[idx].plot(x, y, color='black', linewidth=16, zorder=0)

    norm = plt.Normalize(speed.min(), speed.max())
    lc = LineCollection(segments, cmap='plasma', norm=norm, linewidth=5)
    lc.set_array(speed)
    axes[idx].add_collection(lc)

    axes[idx].set_aspect('equal')
    axes[idx].axis('off')
    axes[idx].set_title(driver, color='white', fontsize=16)

plt.tight_layout()
plt.show()

Next steps

Last modified on March 6, 2026