Guides
Tyre degradation
Degradation stint by stint and per compound, and how much to trust each rate.
Tyre wear and fuel burn pull lap times in opposite directions: a stint whose raw times stay flat is a tyre going off at the rate the car gets lighter. lapbox.tyres takes the fuel out first, then measures the trend two ways — stint by stint, and one line per compound across the field.
The examples use Monza 2025, a circuit that barely wears tyres. That makes it a good place to see how much a degradation number can be trusted.
Stint by stint
import fastf1
from lapbox.tyres import compound_summary, stint_degradation
session = fastf1.get_session(2025, "Monza", "R")
session.load(telemetry=False, weather=False, messages=False)
stints = stint_degradation(session.laps)
print(stints[stints["driver"].isin(["VER", "NOR"])].round(3).to_string(index=False))driver team stint compound laps median_corrected deg_per_lap VER Red Bull Racing 1 MEDIUM 36 81.327 0.006 VER Red Bull Racing 2 HARD 15 80.989 0.032 NOR McLaren 1 MEDIUM 45 81.631 0.007 NOR McLaren 2 SOFT 6 80.970 0.043
Each stint’s timed, non-pit laps are fuel-corrected and kept within 107 % of the stint’s best; deg_per_lap is the slope of what’s left against lap number. A stint needs three such laps to appear, and a three-lap stint is a weak trend.
By compound
compound_summary takes the median slope per compound, so one driver’s ruined stint doesn’t define a compound:
print(compound_summary(stints).round(3).to_string(index=False))compound stints laps median_deg best_deg worst_deg
SOFT 3 20 -0.039 -0.149 0.043
MEDIUM 15 404 -0.001 -0.091 0.024
HARD 16 489 0.005 -0.026 0.061The per-compound model
TyreDegradationModel fits one straight line per compound over every driver: fuel-corrected lap time against tyre age. Clean the laps first — its 107 % filter catches safety-car laps, not every slow one:
from lapbox.pace import LapCleaningPipeline
from lapbox.tyres import TyreDegradationModel
model = TyreDegradationModel().fit(LapCleaningPipeline().run(session.laps))
print(model.summary().round(3).to_string(index=False))compound degradation_s_per_lap intercept_s fuel_coef r2 laps
SOFT -0.133 82.673 0.048 0.173 24
MEDIUM -0.008 82.289 0.048 0.021 399
HARD 0.014 82.137 0.048 0.067 491fuel_coef is the correction applied per lap of fuel (0.048 s, the same constant as everywhere else). intercept_s is the lap time on a new tyre with the fuel all burned.
print(f"{model.degradation_rate('HARD'):+.3f} s/lap")
print(f"{model.predict_time_loss('HARD', 20):+.2f} s after 20 laps")
hard = model.compounds["HARD"]
print(hard.laps, round(hard.r2, 3), round(hard.fuel_coef, 3))+0.014 s/lap +0.27 s after 20 laps 491 0.067 0.048
TyreDegradationModel.predict_time_loss is rate × age, against a fresh tyre. A compound that wasn’t fitted — fewer than five laps, or one tyre age — raises a KeyError.
How far to trust a rate
Both methods say the soft got quicker with age at Monza, on 20–24 laps. Neither is a measurement of the tyre alone: the slopes also carry track evolution, the fuel assumption and who ran which stint. The low r2 is the honest part: tyre age explains little of how the lap times varied here.
- Read every rate with its laps (and, for the model, its
r2). - Low-wear circuits give small, noisy slopes. Over 65 races of 2024–2026, 23 % of whole-race compound rates from the model still came out negative. lapbox reports the fit as it comes out; clamp it (at zero, say) before planning a strategy with it.
- Rain tyres mostly drop out of a mixed race. The 107 % filter keeps laps against the driver’s best of the race, usually on slicks: of eight rain-tyre fits in those 65 races, five went and two kept under a third of their laps. Fit rain tyres on their own laps.
These docs describe lapbox 0.1.0. Something wrong or missing? Open an issue.