Skip to main content

The intensity-duration modelling toolkit for endurance sports. Scikit-learn compatible.

Project description

Silhouette

The intensity-duration modelling toolkit for endurance sports. Scikit-learn compatible.

Try the interactive playground 🚀

Models

Parametric models

Model Parameters
TwoParameterRegressor CP, W'
ThreeParameterRegressor CP, W', P_max
OmniDurationRegressor CP, W', P_max, a, tcp_max

Data-driven models

Model Parameters
FPCARegressor FPC1 (gain), FPC2 (sprint/endurance bias), FPC3 (mid-duration)

Installation

uv add silhouette

Or with pip:

pip install silhouette

Quick start

Parametric models

import numpy as np
from silhouette import OmniDurationRegressor

durations = np.array([5, 10, 30, 60, 120, 300, 600, 1200, 1800, 3600])
power = np.array([1050, 850, 600, 480, 400, 340, 310, 290, 275, 255])

reg = OmniDurationRegressor()
reg.fit(durations.reshape(-1, 1), power)

reg.cp_       # critical power (W)
reg.p_max_    # peak power (W)
reg.w_prime_  # anaerobic work capacity (J)

reg.predict(np.array([[300]]))  # predicted power at 5 minutes

All parametric models share the same interface. Swap OmniDurationRegressor for TwoParameterRegressor or ThreeParameterRegressor and the code works the same way.

FPCA model

from silhouette import FPCARegressor

reg = FPCARegressor.from_model()
reg.fit(durations.reshape(-1, 1), power)

reg.fpc1_     # overall power level
reg.fpc2_     # sprint vs endurance bias
reg.fpc3_     # mid-duration specialization

reg.predict(np.array([[300]]))
reg.percentiles()  # {"fpc1": 72.3, "fpc2": 34.1, "fpc3": 55.8}
reg.z_scores()     # {"fpc1": 0.87, "fpc2": -0.41, "fpc3": 0.14}

Known parameters

When parameters are already known, use curve directly without fitting:

from silhouette import TwoParameterRegressor, FPCARegressor

t = np.arange(1, 3601)
power = TwoParameterRegressor.curve(t, cp=250, w_prime=20_000)
power = FPCARegressor.curve(t, fpc1=0.5, fpc2=-0.1, fpc3=0.0)

Custom bounds

reg = OmniDurationRegressor(
    bounds={"cp": (200, 400), "p_max": (800, 1500)},
    initial_params={"cp": 280},
)

Time to exhaustion

The inverse of the power-duration curve: given a power, how long can it be sustained?

# On a fitted model
tte = reg.predict_inverse(np.array([250, 300, 350]))

# With known parameters
tte = TwoParameterRegressor.curve_inverse(350, cp=250, w_prime=20_000)

Plotting

Install with plotting support:

uv add silhouette[plotting]

Plot data with fitted models (sklearn Display pattern):

from silhouette.plotting import PowerDurationDisplay

# Single model
display = PowerDurationDisplay.from_estimator(reg, durations.reshape(-1, 1), power)

# Compare models
display = PowerDurationDisplay.from_estimators(
    [reg_2p, reg_omni], durations.reshape(-1, 1), power,
)

Power-Duration Models

FPCA mode of variance:

from silhouette.plotting import ModeOfVarianceDisplay

display = ModeOfVarianceDisplay.from_estimator(fpca_reg)

Mode of Variance

References

  • Monod, H., & Scherrer, J. (1965). The work capacity of a synergic muscular group. Ergonomics, 8(3), 329-338.
  • Morton, R. H. (1996). A 3-parameter critical power model. Ergonomics, 39(4), 611-619.
  • Puchowicz, M. J., Baker, J., & Clarke, D. C. (2020). Development and field validation of an omni-domain power-duration model. Journal of Sports Sciences, 38(7), 801-813.
  • Puchowicz, M. J., & Skiba, P. F. (2025). Functional Data Analysis of the Power-Duration Relationship in Cyclists. International Journal of Sports Physiology and Performance, 1(aop), 1-10.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

silhouette-0.4.0.tar.gz (63.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

silhouette-0.4.0-py3-none-any.whl (64.8 kB view details)

Uploaded Python 3

File details

Details for the file silhouette-0.4.0.tar.gz.

File metadata

  • Download URL: silhouette-0.4.0.tar.gz
  • Upload date:
  • Size: 63.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.10

File hashes

Hashes for silhouette-0.4.0.tar.gz
Algorithm Hash digest
SHA256 7dc8189864de1576f24abedb0c166caf33c1e5e1368a611e9d0ce93da930a3d2
MD5 eaf893041dc8a6c5057d5fca2e82238f
BLAKE2b-256 5c25e2d9f087edcad5ce1223130ab2e20889d0a06f5334800a62e4fe81c33dad

See more details on using hashes here.

File details

Details for the file silhouette-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: silhouette-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 64.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.10

File hashes

Hashes for silhouette-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d1852dd2fde96e5bf51dd898d9272e92f7276e1c07ee55de2947fea2d808a405
MD5 7c0681c7ec4192dcca33d83793e8b2ae
BLAKE2b-256 b57168060b0125af829583fa3e175283679c2eed8f9637e6d32a518eb4345a9a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page