Merge the Trace rain tier into Very Light (#212)

The rain-intensity scale had a Trace tier (below the 1st percentile of a place's
rain days) sitting under Very Light — a sliver category that mostly showed 1% and
crowded the distribution strip. Fold it into Very Light, which now bottoms out the
scale at 0, so the lightest measurable rain reads as Very Light.

- grading.py: RAIN_BANDS drops the Trace band; Very Light's floor goes 1 -> 0. The
  detail-view ladder derives from the table, so it follows automatically.
- shared.js: SCALE_RAIN drops the Trace row; Very Light's range becomes "<10".

Eight rain tiers now instead of nine; the strip shows one fewer column. The wet-1
colour token is kept (unreferenced by new gradings) so any day still cached with
the old class renders until the derived store recomputes.

Claude-Session: https://claude.ai/code/session_013dRZmX9D3JEntfMKWMTWZ8
This commit is contained in:
Emi Griffith 2026-07-19 21:25:13 -07:00 committed by GitHub
parent a5f90ad6e3
commit 4520b9e4ba
2 changed files with 15 additions and 3 deletions

View file

@ -47,7 +47,7 @@ TEMP_BANDS = [
# Precipitation is graded ONLY among days that actually rained (>= RAIN_THRESHOLD) # Precipitation is graded ONLY among days that actually rained (>= RAIN_THRESHOLD)
# in the seasonal window — a "rain percentile". Rain is one-directional (heavier = # in the seasonal window — a "rain percentile". Rain is one-directional (heavier =
# more extreme), so these 9 tiers are sequential light->heavy, using the SAME cut # more extreme), so these 8 tiers are sequential light->heavy, using the SAME cut
# points as temperature. Dry days are handled separately (the "dry" class, colored # points as temperature. Dry days are handled separately (the "dry" class, colored
# by dry streak in the UI). Same [lower, upper) convention as TEMP_BANDS. # by dry streak in the UI). Same [lower, upper) convention as TEMP_BANDS.
RAIN_BANDS = [ RAIN_BANDS = [
@ -58,8 +58,8 @@ RAIN_BANDS = [
(40, "Moderate", "wet-5"), # 40-60 (40, "Moderate", "wet-5"), # 40-60
(25, "LightMod", "wet-4"), # 25-40 (25, "LightMod", "wet-4"), # 25-40
(10, "Light", "wet-3"), # 10-25 (10, "Light", "wet-3"), # 10-25
(1, "Very Light", "wet-2"), # 1-10 (0, "Very Light", "wet-2"), # <10 the lightest measurable rain (was two
(0, "Trace", "wet-1"), # <1 lightest measurable rain # tiers, Very Light + Trace, now merged)
] ]

View file

@ -81,6 +81,18 @@ def test_rain_with_no_historical_rain_days_is_extreme():
assert g["percentile"] == 100.0 and g["class"] == "wet-9" assert g["percentile"] == 100.0 and g["class"] == "wet-9"
def test_lightest_rain_day_grades_very_light_not_trace():
# The former "Trace" tier (<1st percentile of rain days) was merged into
# "Very Light", which now bottoms out the scale at 0.
assert "Trace" not in [b[1] for b in grading.RAIN_BANDS]
assert grading.RAIN_BANDS[-1] == (0, "Very Light", "wet-2")
rain = np.arange(1, 201, dtype=float) / 100.0 # 200 rain days: 0.01 .. 2.00
samples = np.concatenate([np.zeros(20), rain])
g = grading._grade_precip(samples, 0.01) # the very lightest -> <1 pct
assert g["percentile"] < 1
assert g["grade"] == "Very Light" and g["class"] == "wet-2"
# ---- dry streaks --------------------------------------------------------------- # ---- dry streaks ---------------------------------------------------------------
def test_dry_streaks_walk(): def test_dry_streaks_walk():