feat(studio): interactive dilution equation, curated backgrounds, custom bimodal modes (schema 0.5.0) - #98
Merged
Conversation
aliakherati
force-pushed
the
feat/background-curation
branch
from
August 21, 2026 04:23
2acf6ba to
d06ae71
Compare
…readout Review requests, all three built: Dilution is now the equation, not just curves. The model's two-piece form is shown -- V/V0 = t^0.8 (t <= 1e4 s), then 1585*exp(k*(t-1e4)^1.5) -- with the selected regime's k beside it. The regimes are chips ON the graph carrying their k values (introspected from coupled/dilution.py's segment tuples, never re-typed; a test compares against the same tuples). Clicking a chip sets dilution.regime through the same server round-trip as any field edit, so choosing on the graph IS choosing in the config. A "try k" box draws the family at any k in [1e-10, 1e-6] as a dashed gold curve, computed by the model's OWN _two_piece/_eval_segment machinery -- at a named regime's k the custom curve equals that regime's curve bit for bit, which is the test that proves it is not a lookalike formula. Marked clearly as a picture: the model runs named regimes or a constant rate. The ERA5 profile hover now reads out the whole level: pressure, altitude, temperature AND water vapour (p 50 hPa / z 20.8 km / T 211.4 K / H2O 4.20 ppmv), tracking the pointer along the PRESSURE axis -- charts gain hoverAxis="y" with a horizontal crosshair and a panel-supplied readout, since only the panel knows what lives at each level. This also retires a latent defect: the old x-tracking hover assumed sorted xs, which a temperature profile does not have. Sub-decade gridlines on log axes (2..9 per decade), faint and dashed so they read as scaffolding: requested for the pressure axis, and the V/V0 axis gets them for free. Panel parameters travel as PreviewRequest.params -- exploration inputs for a picture, deliberately not part of the config, the hash, or anything persistent. 363 Python Tier-A (+3), 60 vitest (+2). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EaDHnPdiacsybr8Tp5WnqR
…tion (schema 0.5.0)
Review requests: offer SABRE-220/310/330 and the geoengineered stratosphere only, and
allow a custom distribution from two (N, sigma, Dp) triplets.
Curated means HIDDEN, not removed. Tier B's archived cases use cesm_g6; a schema that
refused it would disconnect the archive from its own configurations. So the enum keeps
every member, SciField gains `hidden_choices`, and the form generator filters them from
the picker -- an archival value still displays when it IS the current value, marked
"(archival)". The picker now offers sabr_330, sabr_310, sabr_220, aer_geo (the spec's
GEOENG reference: Pierce et al. AER 2D), and custom.
CUSTOM is two lognormal modes -- (N1, Dp1, sigma1), (N2, Dp2, sigma2) -- plus an explicit
STP/ambient basis, because the bridge refuses a custom mode list without one (the
per-dataset basis trap SCIENCE-3 recorded). Defaults are SABR-220's mode with N2 = 0:
custom starts citable and unimodal, and with untouched defaults it seeds the SAME bins as
sabr_220, asserted bin for bin. The size-distribution panel redraws live as the modes are
typed, through the same to_scenario -> initial_tomas_state path the run uses.
Found by test at the seam: the model refuses zero-N modes outright ("N must be > 0"), so
the seam FILTERS them -- N2 = 0 means a one-mode list, not a zero entry -- and refuses the
all-zero case with a message naming the fields rather than the bridge internals.
Also from review: the max-wall-time description cited "BLOCKING-4" bare, which read as a
mystery label; it now says what the cap does and where the hour came from.
371 Python Tier-A, 60 vitest. Hash ...d35ba6 -> ...2c09c6 (0.5.0): default run unchanged,
seven more fields describing it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EaDHnPdiacsybr8Tp5WnqR
…ntrol that fixes it Two review corrections. The campaign is SABRE -- Stratospheric Aerosol processes, Budget and Radiative Effects. Enum members and values are respelled (sabre_220/310/330, shown as such in the picker and the legacy page), and studio/modelio translates them to the model's internal sabr_* keys: the bridge's BACKGROUND_MODES naming is the model's own, and renaming model internals is not the seam's call. Hash repinned within the still-unmerged 0.5.0. The dilution explorer's error handling was a trap of my own making: a rejected k came back as a panel-level 422 that REPLACED the panel body -- taking with it the chips, the chart, and the very input needed to fix the value, while the bad k stayed pinned so every refetch re-failed. Unrecoverable without a reload; reported from use with a screenshot. Two-part fix: Frame renders errors ABOVE its content instead of instead of it (an error must never remove the control that clears it), and the k box validates against the bounds the server declares before any request, with the message inline at the input. Verified live: k=10 shows "k must be within 1e-10 ... 1e-6" beside the box with everything still interactive, and 1.5e-8 recovers on the next keystroke. 371 Python Tier-A, 60 vitest. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EaDHnPdiacsybr8Tp5WnqR
aliakherati
force-pushed
the
feat/background-curation
branch
from
August 27, 2026 01:26
d06ae71 to
c939b5f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Interactive dilution, full-profile hover, curated backgrounds, custom modes
Four review requests in one message; two stacked PRs deliver them. This branch carries both commits
(the first is also PR #98's base): schema 0.4.0 → 0.5.0.
The dilution tab is now the equation (first commit)
The model's two-piece form is displayed with the selected regime's constant beside it:
coupled/dilution.py's own segment tuples, never re-typed (a test compares against the sametuples). Clicking a chip sets
dilution.regimefor the run — choosing on the graph ischoosing.
_two_piece/_eval_segmentmachinery. At a named regime's k the custom curve equals thatregime's bit for bit — the test that proves it is not a lookalike formula. Clearly marked a
picture: the model runs named regimes or a constant rate.
p 50 hPa · z 20.8 km · T 211.4 K · H₂O 4.20 ppmv), tracking along the pressure axis. Also retires a latent defect:the x-tracking hover assumed sorted xs, which a temperature profile does not have.
Curated backgrounds — hidden is not removed (second commit)
Picker now offers: sabr_330, sabr_310, sabr_220, aer_geo (the spec's GEOENG reference — Pierce
et al. AER 2D), custom. Hidden: redcircles, cesm_g6, cesm_g6_amb — still valid, because Tier
B's archived cases use cesm_g6, and a schema that refused them would disconnect the archive from its
own configurations.
SciField.hidden_choicesis what the generator filters on; an archival valuestill displays, marked "(archival)".
Custom bimodal distribution
(N₁, Dp₁, σ₁) + (N₂, Dp₂, σ₂) with an explicit STP/ambient basis — required because the
bridge refuses a custom mode list without one (SCIENCE-3's per-dataset basis trap, made a field).
Defaults are SABR-220's mode with N₂ = 0: custom starts citable and unimodal, and with untouched
defaults it seeds the same bins as sabr_220, asserted bin-for-bin. The panel redraws live as you
type, through the same
to_scenario → initial_tomas_statepath the run uses.Found by test at the seam: the model refuses zero-N modes (
N must be > 0), so the seam filtersthem — N₂ = 0 is a one-mode list, not a zero entry — and refuses the all-zero case with a message
naming the fields.
Also
max_wall_time_sno longer cites "BLOCKING-4" bare — raised in review as confusing, which it was.It now says what the cap does and where the hour came from.
371 Python Tier-A, 60 vitest, both lanes green. Verified live in the browser: chip click changed
the run's regime; typing N₂ = 8 drew the bimodal distribution on the spot.