Skip to content

feat(studio): the release date is a month and a day (SCIENCE-1 answered) - #93

Merged
aliakherati merged 1 commit into
studio/devfrom
feat/calendar-date-input
Aug 18, 2026
Merged

feat(studio): the release date is a month and a day (SCIENCE-1 answered)#93
aliakherati merged 1 commit into
studio/devfrom
feat/calendar-date-input

Conversation

@aliakherati

Copy link
Copy Markdown
Collaborator

SCIENCE-1 is answered, and the date follows from the answer

Zonal-mean, monthly climatology (your call, 2026-08-18), selected by the month of the release. So
the reduced product will be (lat × month × level) — order 86k values per field, a few MB, small
enough to commit with a checksum rather than fetch at run time. Recorded on #53 and in
OPEN_QUESTIONS.md; task 1.1 is unblocked.

That decides the shape of the date, which is what this PR builds.

before after
entered day_of_year: int (1–366) month + day_of_month
derived day_of_year, on a fixed non-leap calendar
year n/a none — a monthly climatology is an average over years

A monthly climatology has no year, so accepting one would imply the run used that year's weather.
And day_of_year must be derived rather than entered alongside the month: entering both permits a
config whose month and day disagree — the climatology read at one date and the sun at another.

Non-leap is a declaration, not an oversight

studio/science/calendar.py owns it. The same date in a leap year is day 173, and the solar
declination differs by ~0.01° — far below the uncertainty in anything it feeds. The fixed calendar
buys a config that means one thing forever, and the test pins the value that ties it to the archive:

21 June  →  day 172        # exactly what the paper ensemble uses

29 and 31 February are refused, not clamped — in the schema as well as in the derivation, so the
error names the two fields the user typed rather than a calendar function.

Verified in the browser

month  6 day 21 -> day 172        month  2 day 30 -> 422 "February has 28 days on the
month 12 day 21 -> day 355                            non-leap calendar (SCIENCE-1)"
month  1 day  1 -> day 1

And the SZA panel follows the date, with the physics checking out at 30°N:

June      13.74 h daylight   min SZA  6.55°     (|30 − 23.44| =  6.56)
December   9.93 h daylight   min SZA 53.42°     ( 30 + 23.44  = 53.44)

Also

The model seam now refuses an unresolved day_of_year the same way it refuses an unresolved
concentration — a raw config reaching the model would otherwise pick a solar declination of its own.

346 Python Tier-A (+19), 55 vitest, lint and mypy clean. No UI code: the date fields render on
stage 1 with their units and provenance because the form is generated.

The hash moved again inside the still-unmerged 0.3.0 (…6d3a73 → …7813ae). Same run — the same 21 June
— described differently.

Stacked on #92, which is stacked on #90. Merge in that order and I'll rebase anything GitHub
flags.

…r (SCIENCE-1)

SCIENCE-1 is answered: the climatology is a ZONAL-MEAN, MONTHLY average, selected by the
month of the release. That decides the shape of the date, so the two land together.

A monthly climatology is an average over years, so there is no year to give -- accepting
one would imply the run used that year's weather. schedule.month and schedule.day_of_month
are entered; day_of_year is DERIVED on a fixed non-leap calendar. Entering both would allow
a config whose month and day disagree: the climatology read at one date and the sun at
another.

studio/science/calendar.py owns the convention. Non-leap is a declaration, not an
oversight: the same date in a leap year is day 173 and the solar declination differs by
about 0.01 degrees, far below the uncertainty in anything it feeds, and the fixed calendar
buys a config that means one thing forever. The test pins the value that ties it to the
archive -- 21 June is day 172, the ensemble's number, now derived rather than typed.

29 and 31 February are refused rather than clamped, in the schema as well as in the
derivation, so the error names the fields the user typed.

Verified in the browser: 21 June -> 172, 21 December -> 355, 1 January -> 1, 30 February ->
422 with the calendar's own message. The SZA panel follows: 13.74 h of daylight in June
against 9.93 h in December at 30N, with a December minimum SZA of 53.42 degrees against the
30 + 23.44 = 53.44 the geometry demands.

The model seam refuses an unresolved day_of_year the same way it refuses an unresolved
concentration; a raw config reaching the model would pick a declination of its own.

Docs: SCIENCE-1 marked answered with its consequences, task 1.1 unblocked in PHASE_1.md
(still needs a source decision -- and BLOCKING-5's note that reanalysis stratospheric water
vapour is biased dry suggests H2O may want a different source from p and T).

346 Python Tier-A (+19). Hash moved again within the unmerged 0.3.0 (...6d3a73 ->
...7813ae): the default run is the same 21 June, described differently.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EaDHnPdiacsybr8Tp5WnqR
@aliakherati
aliakherati force-pushed the feat/calendar-date-input branch from 6547018 to bfc4225 Compare August 18, 2026 18:53
@aliakherati
aliakherati merged commit f463698 into studio/dev Aug 18, 2026
2 checks passed
@aliakherati
aliakherati deleted the feat/calendar-date-input branch August 18, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant