NRCD performance standardization formulas (cross country, track, road)
Project description
nrcd
Python library for National Running Club Database (NRCD) performance standardization (cross country, track, road). Implements the formulas documented in the NRCD resource paper.
Use this to standardize your own race results — no NRCD dataset download required.
Quick start
Times can be seconds or clock strings ("22:15", "4:12.00", "10.52"). XC distances accept m/km/mi or labels like "5k". Invalid time, distance, or unit strings raise ValueError with a short hint (they do not return NaN silently).
Cross country — 5K in 22:15
from nrcd import standardize_xc # or: from nrcd.standardize import standardize_xc
std = standardize_xc("22:15", gender="M", reported_distance="5k")
Cross country — 8 km with weather, grade, altitude
std = standardize_xc(
"27:30",
gender="M",
reported_distance=8,
distance_unit="km",
actual_distance=8.01,
temperature=72, # °F (default)
dew_point=65,
elevation_gain=2.5, # % grade (default)
elevation_loss=2.5,
meet_elevation=5200, # feet (default)
)
Outdoor track — 100m with wind
from nrcd import standardize_outdoor_track
std = standardize_outdoor_track(
"13.52",
gender="F",
event_name="100m",
wind_mps=2.0,
)
Indoor track — 200m on a banked 200m oval
from nrcd import standardize_indoor_track
std = standardize_indoor_track(
"21.80",
gender="M",
event_name="200m",
lap_length_m=200,
banked=True,
)
Road — half marathon with weather and grade
from nrcd import standardize_road
std = standardize_road(
"1:25:30",
gender="F",
event_name="Half Marathon",
temperature=55,
dew_point=48,
elevation_gain=1.2,
elevation_loss=1.2,
)
Pipelines
| Sport | Function | What differs |
|---|---|---|
| Cross country | standardize_xc |
Weather, grade, altitude, then Riegel to NIRCA 8k/6k |
| Road | standardize_road |
Same weather / grade / altitude as XC; distance from event_name; no Riegel target |
| Outdoor track | standardize_outdoor_track |
Sprint wind, weather, grade, altitude |
| Indoor track | standardize_indoor_track |
Lap/bank venue factors; no wind |
standardize_result remains available when you need a custom sport_name string.
Unit switches (optional kwargs on all pipelines):
| Field | Default | Alternative |
|---|---|---|
temperature, dew_point |
°F | temp_unit="C" |
meet_elevation |
feet | venue_elevation_unit="m" |
elevation_gain, elevation_loss |
% grade | grade_input="feet" or "m" |
More examples
Runnable scripts in examples/:
load_dataset_example.py exits with code 1 if Zenodo CSVs are not in data/ — that is expected without the optional dataset.
pip install nrcd
python examples/xc_examples.py
python examples/track_outdoor_examples.py
Install
Requires Python 3.10+.
pip install nrcd # after first PyPI release
pip install "nrcd[apis]" # optional: weather / elevation APIs
pip install "nrcd[data]" # optional: Zenodo CSV helpers (pandas)
Until the package is on PyPI, install from source:
git clone https://github.com/National-Running-Club-Database/nrcd
cd nrcd
pip install -e .
From source (development):
git clone https://github.com/National-Running-Club-Database/nrcd
cd nrcd
pip install -e ".[dev]"
pip install -e ".[dev,apis]"
API keys (optional — nrcd.enrich only)
Standardization does not need API keys. Use enrichment only when backfilling weather or meet altitude from city/state.
pip install "nrcd[apis]"→
→ set
NRCD_OPENWEATHER_API_KEY- For weather at a race date/time, also
→
NRCD_TIMEZONE_API_KEY - Meet altitude uses free USGS EPQS (no key) after OpenWeather geocodes the city
export NRCD_OPENWEATHER_API_KEY="your_key"
export NRCD_TIMEZONE_API_KEY="your_key" # weather only
Live tests (optional): copy local_api_keys.env.example → local_api_keys.env (gitignored), add your OpenWeather key, then pytest -m live_api -v. AQI history starts 2020-11-27; default test date is 2024-10-12.
Full walkthrough: . In Python:
from nrcd.enrich import API_GUIDE; print(API_GUIDE).
Historical OpenWeather timemachine weather may require a paid OpenWeather plan; geocoding + USGS altitude often work on the free tier.
Do you need the NRCD dataset?
| Use case | Zenodo CSVs needed? |
|---|---|
| Standardize your own results | No |
examples/ scripts |
No |
nrcd.enrich API backfill |
No |
examples/load_dataset_example.py only |
Yes (optional) |
Optional public export: (see
).
API
Full parameter tables: from nrcd import PARAMETERS_DOC or help(nrcd.standardize).
Entry points
| Function | Use for |
|---|---|
standardize_xc |
Cross country — distance in m/km/mi; Riegel to NIRCA targets |
standardize_road |
Road / marathon — event_name; weather, grade, altitude |
standardize_outdoor_track |
Outdoor track — event_name; wind on sprints |
standardize_indoor_track |
Indoor track — event_name; lap length / banking |
standardize_result |
Low-level — any sport_name (advanced) |
standardize_seconds |
Dispatch from a RaceContext / XCRaceContext row |
enrich_race_context |
Fill missing weather/altitude on a context (pip install "nrcd[apis]") |
nrcd.standardize — pipelines & context
| Name | Description |
|---|---|
RaceContext |
Dataclass for one result (XC or track); time_str or time_sec |
XCRaceContext |
XC-focused RaceContext subclass |
StandardizeConfig |
Paper coefficients (Riegel exponents, heat k, grade bases, …) |
PARAMETERS_DOC |
Full required/optional parameter reference (text) |
PARAMETER_SPECS |
Same metadata as structured ParameterSpec tuples |
parameter_specs() |
Return PARAMETER_SPECS |
| `required_for("xc" | "road" |
nrcd.standardize — time, distance, units
| Name | Description |
|---|---|
parse_time |
"22:15", "1:10:13", or seconds → float seconds |
format_time |
Seconds → clock string |
parse_distance |
"5k", 8, "8000m" + unit → meters |
distance_to_meters |
Numeric distance with distance_unit (m / km / mi) |
c_to_f, f_to_c |
Temperature conversion |
feet_to_meters, meters_to_feet |
Length conversion |
temperature_to_fahrenheit |
Value + temp_unit (F / C) → °F |
venue_elevation_to_feet |
Meet altitude + venue_elevation_unit (ft / m) → ft |
grade_percent_from_feet |
Vertical ft over course → % grade |
grade_percent_from_meters |
Vertical m over course → % grade |
resolve_grade_percent |
Normalize gain/loss with grade_input (percent / feet / m) |
nrcd.standardize — factors & sport helpers
| Name | Description |
|---|---|
weather_factor |
Heat slowdown multiplier from temp + dew point (°F) |
heat_index, heat_slowdown_percent |
Hadley-style heat index components |
elevation_factor |
Maurer grade multiplier from % gain/loss |
apply_course_grade_factor |
Grade step on a race time |
warn_one_sided_course_grade |
Warn when only gain or only loss is set |
apply_meet_altitude |
Peronnet meet-altitude correction |
peronnet_f_alt, sea_level_time_seconds |
Altitude factor and sea-level equivalent |
resolve_meet_altitude_inputs |
Parse elevation + barometric pressure from a record |
barometric_pressure_hpa_from_record |
hPa from row fields |
barometric_pressure_torr_from_hpa, parse_barometric_pressure_hpa |
Pressure unit helpers |
riegel_convert, riegel_exponent |
Distance conversion |
xc_target_distance_m |
NIRCA reference XC distance (8000 M / 6000 F) |
apply_factors |
Multiply time by weather/grade/altitude/track/wind factors |
is_cross_country, is_track, is_outdoor_track, is_indoor_track |
Sport name checks |
normalize_sport_name, pipeline_kind |
Sport string normalization / xc vs track |
nrcd.data — Zenodo CSV helpers
| Name | Description |
|---|---|
meet_altitude_column |
Altitude column name in a meet DataFrame |
meet_altitude_ft_from_record |
Meet altitude (ft) from a merged row + course details |
derive_course_details_fields |
Derived weather/grade fields from course details |
nrcd.enrich — optional APIs (pip install "nrcd[apis]")
Citation
NRCD: An Open Database of Collegiate Running with Unified Performance Standardization
Jonathan A. Karr Jr, Ryan M. Fryer, Ben Darden, Nicholas Pell, Kayla Ambrose, Evan Hall, Ramzi K. Bualuan, and Nitesh V. Chawla.
arXiv preprint (forthcoming).
Dataset (if using Zenodo export):
Author
Development
pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nrcd-0.1.0.tar.gz.
File metadata
- Download URL: nrcd-0.1.0.tar.gz
- Upload date:
- Size: 53.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e464114733b2c31fc485a591956cd1373778455bf2636b123d611009da5d772
|
|
| MD5 |
d01beb67c84f02f276d189f3b2f8b0fa
|
|
| BLAKE2b-256 |
6f4fbfc8c1cbaec2cc42c6b7ec73c676bc4d50a0ff83fa5d261d2b3726d9c846
|
Provenance
The following attestation bundles were made for nrcd-0.1.0.tar.gz:
Publisher:
publish.yml on National-Running-Club-Database/nrcd
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nrcd-0.1.0.tar.gz -
Subject digest:
6e464114733b2c31fc485a591956cd1373778455bf2636b123d611009da5d772 - Sigstore transparency entry: 1740707070
- Sigstore integration time:
-
Permalink:
National-Running-Club-Database/nrcd@1e7f6116c81aa4b1cc379e014ff63b39ef25acdc -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/National-Running-Club-Database
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1e7f6116c81aa4b1cc379e014ff63b39ef25acdc -
Trigger Event:
push
-
Statement type:
File details
Details for the file nrcd-0.1.0-py3-none-any.whl.
File metadata
- Download URL: nrcd-0.1.0-py3-none-any.whl
- Upload date:
- Size: 51.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c354eaa7692f981537362cf03440bbfb1bcd7c10e78465c3d174b6dee148f5fc
|
|
| MD5 |
bf7803211ea0d97965ad7eb9e7b9e808
|
|
| BLAKE2b-256 |
d29588f193eb97549bc49e5d7b4585de680b8d778a06406217ad82989feade42
|
Provenance
The following attestation bundles were made for nrcd-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on National-Running-Club-Database/nrcd
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nrcd-0.1.0-py3-none-any.whl -
Subject digest:
c354eaa7692f981537362cf03440bbfb1bcd7c10e78465c3d174b6dee148f5fc - Sigstore transparency entry: 1740707094
- Sigstore integration time:
-
Permalink:
National-Running-Club-Database/nrcd@1e7f6116c81aa4b1cc379e014ff63b39ef25acdc -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/National-Running-Club-Database
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1e7f6116c81aa4b1cc379e014ff63b39ef25acdc -
Trigger Event:
push
-
Statement type: