Rename the middle rain tiers and merge Mod–Heavy into Heavy (#214)
The rain-intensity scale drops its two hyphenated compound labels for single words and loses a tier, going from eight to seven: Trace / Light / Brisk / Typical / Heavy / Very Heavy / Extreme - Light–Mod -> Brisk, Moderate -> Typical (renames only; classes unchanged). - Mod–Heavy is merged up into Heavy, whose floor drops from the 75th to the 60th rain-day percentile, so Heavy now spans 60–90. - The lightest tier (already the merged Very Light) is renamed Trace. grading.py RAIN_BANDS and the frontend SCALE_RAIN mirror stay in lockstep, and the detail-view ladder derives from the table so it follows automatically. The now-unreferenced wet-6 colour token is kept so any day still cached under that class renders until the derived store recomputes; the chart's percentile fan also keeps it for a smooth gradient. Claude-Session: https://claude.ai/code/session_013dRZmX9D3JEntfMKWMTWZ8
This commit is contained in:
parent
c9abad3e13
commit
581bdaca04
2 changed files with 22 additions and 18 deletions
12
grading.py
12
grading.py
|
|
@ -47,19 +47,17 @@ 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 8 tiers are sequential light->heavy, using the SAME cut
|
# more extreme), so these 7 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 = [
|
||||||
(99, "Extreme", "wet-9"), # heaviest rain for the season (darkest)
|
(99, "Extreme", "wet-9"), # heaviest rain for the season (darkest)
|
||||||
(90, "Very Heavy", "wet-8"), # 90-99
|
(90, "Very Heavy", "wet-8"), # 90-99
|
||||||
(75, "Heavy", "wet-7"), # 75-90
|
(60, "Heavy", "wet-7"), # 60-90 (the old Mod–Heavy tier merged in)
|
||||||
(60, "Mod–Heavy", "wet-6"), # 60-75
|
(40, "Typical", "wet-5"), # 40-60 (was Moderate)
|
||||||
(40, "Moderate", "wet-5"), # 40-60
|
(25, "Brisk", "wet-4"), # 25-40 (was Light–Mod)
|
||||||
(25, "Light–Mod", "wet-4"), # 25-40
|
|
||||||
(10, "Light", "wet-3"), # 10-25
|
(10, "Light", "wet-3"), # 10-25
|
||||||
(0, "Very Light", "wet-2"), # <10 the lightest measurable rain (was two
|
(0, "Trace", "wet-2"), # <10 the lightest measurable rain
|
||||||
# tiers, Very Light + Trace, now merged)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,11 +69,11 @@ def test_dry_day_gets_dry_class_without_percentile():
|
||||||
|
|
||||||
def test_rain_percentile_ranks_among_rain_days_only():
|
def test_rain_percentile_ranks_among_rain_days_only():
|
||||||
# 7 dry days + rain days [0.1, 0.2, 0.4]; 0.2 ranks among the 3 rain days:
|
# 7 dry days + rain days [0.1, 0.2, 0.4]; 0.2 ranks among the 3 rain days:
|
||||||
# less=1, equal=1 -> (1 + 0.5) / 3 = 50% -> Moderate, unaffected by the dry mass.
|
# less=1, equal=1 -> (1 + 0.5) / 3 = 50% -> Typical, unaffected by the dry mass.
|
||||||
samples = np.array([0.0] * 7 + [0.1, 0.2, 0.4])
|
samples = np.array([0.0] * 7 + [0.1, 0.2, 0.4])
|
||||||
g = grading._grade_precip(samples, 0.2)
|
g = grading._grade_precip(samples, 0.2)
|
||||||
assert g["percentile"] == 50.0
|
assert g["percentile"] == 50.0
|
||||||
assert g["grade"] == "Moderate"
|
assert g["grade"] == "Typical"
|
||||||
|
|
||||||
|
|
||||||
def test_rain_with_no_historical_rain_days_is_extreme():
|
def test_rain_with_no_historical_rain_days_is_extreme():
|
||||||
|
|
@ -81,16 +81,22 @@ 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():
|
def test_rain_scale_labels_and_merges():
|
||||||
# The former "Trace" tier (<1st percentile of rain days) was merged into
|
# The seven-tier scale: Trace / Light / Brisk / Typical / Heavy / Very Heavy /
|
||||||
# "Very Light", which now bottoms out the scale at 0.
|
# Extreme. Light–Mod and Moderate were renamed; Mod–Heavy was merged up into
|
||||||
assert "Trace" not in [b[1] for b in grading.RAIN_BANDS]
|
# Heavy (which now floors at the 60th percentile).
|
||||||
assert grading.RAIN_BANDS[-1] == (0, "Very Light", "wet-2")
|
labels = [b[1] for b in grading.RAIN_BANDS]
|
||||||
rain = np.arange(1, 201, dtype=float) / 100.0 # 200 rain days: 0.01 .. 2.00
|
assert labels == ["Extreme", "Very Heavy", "Heavy", "Typical", "Brisk", "Light", "Trace"]
|
||||||
|
for gone in ("Very Light", "Light–Mod", "Moderate", "Mod–Heavy"):
|
||||||
|
assert gone not in labels
|
||||||
|
# A rain day at the old Mod–Heavy range (60–75 pct) is now Heavy.
|
||||||
|
rain = np.arange(1, 201, dtype=float) / 100.0
|
||||||
samples = np.concatenate([np.zeros(20), rain])
|
samples = np.concatenate([np.zeros(20), rain])
|
||||||
g = grading._grade_precip(samples, 0.01) # the very lightest -> <1 pct
|
g = grading._grade_precip(samples, 1.35) # ~67th percentile of rain days
|
||||||
assert g["percentile"] < 1
|
assert 60 <= g["percentile"] < 75 and g["grade"] == "Heavy" and g["class"] == "wet-7"
|
||||||
assert g["grade"] == "Very Light" and g["class"] == "wet-2"
|
# The lightest measurable rain is Trace, bottoming the scale at 0.
|
||||||
|
g0 = grading._grade_precip(samples, 0.01)
|
||||||
|
assert g0["grade"] == "Trace" and g0["class"] == "wet-2"
|
||||||
|
|
||||||
|
|
||||||
# ---- dry streaks ---------------------------------------------------------------
|
# ---- dry streaks ---------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue