Surfaces¶
Requires the viz extra for the widgets (pip install "longeron[viz]");
the measure runners reach their engines lazily (the mdao extra for the
sizing what-if, the mesh engine ships with the core).
Design: Model-defined analysis surfaces.
The declaration the engine derives from is model content: see
examples/deepscout/surfaces.sysml (the ScoutSurfaces package) and the
LongeronSurfaces rendering vocabulary shipped beside the vendored
standard library.
Model-declared analysis surfaces: derive the dashboard from the model.
Design: docs/design/surfaces.md (adopted
2026-08-30), phase 1. A dashboard is a standard view usage: its
expose members select the content – a subject plus analysis and
verification cases – and each panel is a nested view usage whose
render reference names a LongeronSurfaces rendering (the
vendored-stdlib-adjacent extension library). surface() turns
that declaration into a composed ipywidgets surface:
each analysis case becomes a what-if card: its
inparameters are sliders whose bounds are MINED from the model’s own constraints (longeron.analysis.verify.attribute_domains()–assumeconstraints in the case objective, or the subject’s own constraint bounds reached through the parameter’s default binding), the@ToolExecutionannotation names the engine that re-measures on every move, and the named returns are the readout;each verification case becomes a verdict panel: the
verifymembers name the requirement rows, evaluated through the interpreter (check_requirement()), with the verdict stated in the standard’sVerdictKindvocabulary (pass/fail/inconclusive/error);results flow between panels ONLY through the model’s explicit result bindings (
attribute :>> measured = case.result;– the corpus spelling, and the one spelling recognized); a case result no binding names is listed in the wiring map as anunbounddiagnostic, so a forgotten coupling is loud;subject typing is the applicability test: a case applies to the surface’s subject when the subject’s specialization chain reaches the case’s declared subject type. A case that does not apply renders as HONEST ABSENCE – the panel stays in the layout, dimmed, stating the subject type it needs – and swapping the subject (
surface(..., subject=...), the picker dropdown, orbox.swap(...)) re-derives every panel.
The returned widget carries the derivation as data: box.panels (one
Panel per declared subview) and box.wiring – the printable
WiringMap recording which binding fired for every coupling,
the range source per slider, unbound results, and honest absences.
Renderings bind to widget builders through RENDERINGS, a Python
registry keyed by rendering qualified name (the
longeron.views.VIEW_DEFINITIONS mapping-table precedent). Phase 1
registers the two engine-built panels the proof needs (the what-if card
and the verdict cards); the remaining vocabulary entries are declared
and render as honest absence until their builders land.
Requires the viz extra for the widgets:
pip install "longeron[viz]".
- longeron.analysis.surfaces.RANGE_MINED = 'mined-from-constraint'¶
the wiring map’s range-source vocabulary (honesty requirement: the printable map states, per slider, where its bounds came from)
- longeron.analysis.surfaces.RENDERINGS: dict[str, str] = {'LongeronSurfaces::asActionDiagram': 'action_diagram', 'LongeronSurfaces::asMeshViewer': 'mesh_viewer', 'LongeronSurfaces::asMissionGlobe': 'mission_viewer', 'LongeronSurfaces::asReplayPlayer': 'replay_widget', 'LongeronSurfaces::asScoreboard': 'scoreboard', 'LongeronSurfaces::asSizingCards': 'sizing cards', 'LongeronSurfaces::asStateDiagram': 'state_diagram', 'LongeronSurfaces::asStructureDiagram': 'structure_diagram', 'LongeronSurfaces::asVerdictCards': 'verdict cards', 'LongeronSurfaces::asWhatIfCard': 'what-if card'}¶
rendering qualified name -> the widgets-catalog entry (or engine-built panel) it names; the registry the
renderreferences dispatch through. A rendering with no phase-1 builder renders as honest absence naming this table.
- class longeron.analysis.surfaces.Coupling(source, target, binding)[source]¶
Bases:
objectOne explicit result binding that fired: source -> target.
- class longeron.analysis.surfaces.Panel(name, rendering, builder, case='', absent=False, reason='', sliders=<factory>, ranges=<factory>, returns=(), results=<factory>, verdict='', rows=<factory>, tool=None, readout=None, widget=None, repaint=None)[source]¶
Bases:
objectOne declared subview, derived (or honestly absent).
- class longeron.analysis.surfaces.RangeInfo(case, parameter, lo, hi, source, mined_lo=None, mined_hi=None, mined_from=())[source]¶
Bases:
objectOne derived slider’s bounds, with their provenance.
sourceis one ofRANGE_MINED(suffixed with the mined constraints’ qualified names),RANGE_OVERRIDDEN, orRANGE_FALLBACK. An override never erases what the model states:mined_lo/mined_hikeep the constraint bounds, and the case evaluation still tells the truth about values outside them.
- class longeron.analysis.surfaces.SurfaceWidget(*args, **kwargs)[source]¶
Bases:
ProtocolWhat
surface()returns: an ipywidgetsVBox(displayable as usual) carrying the derivation as data. The attributes below are the composite’s kernel-side surface – everything a notebook or test reads and scripts;swapre-derives every panel for another subject (the picker’s programmatic twin).- swap: Callable[[str | Definition], None]¶
re-derive for a subject
- longeron.analysis.surfaces.VerdictKind¶
the standard
VerdictKindvocabulary a verdict panel aggregates to ("error"is the honest extra state: the evaluation itself failed), cross-asserted against the tone table by the test suitealias of
Literal[‘pass’, ‘fail’, ‘inconclusive’, ‘error’]
- class longeron.analysis.surfaces.WiringMap(view, subject, panels=<factory>, ranges=<factory>, couplings=<factory>, unbound=<factory>, absences=<factory>, notes=<factory>)[source]¶
Bases:
objectThe derived wiring, printable:
print(box.wiring).Everything the surface wired – and everything it honestly did not: which binding fired for every coupling, the range source per slider, case results no binding names (
unbound), and the panels that do not apply to the subject (absences).
- longeron.analysis.surfaces.surface(model, view, *, subject=None, ranges=None)[source]¶
Derive the composed dashboard a view usage declares.
viewnames the surface’s view usage (qualified name or element). Its ownexposenames the home subject; each nested view usage is one panel, deriving through its ownexpose(the content: an analysis or verification case) andrender(the presentation: a rendering theRENDERINGSregistry maps to a builder).subjectre-targets the whole surface at another definition (a qualified name or the element). Applicability re-derives: cases whose subject type the new subject does not reach render as honest absence, stating the type they need.rangesoverrides the mined slider bounds per parameter –ranges={"loiterSpeed": (8.0, 30.0)}– keyed by the in-parameter’s name or qualified spelling (<case qname>::<name>or the parameter’s own qualified name). A key matching no parameter, a key matching more than one, or bounds withlo >= hiare refused loudly. An override REPLACES the mined range for that slider only; every other slider stays mined. It is a UI freedom, not a model edit: the mined bounds stay recorded (RangeInfo.mined_lo/mined_hi, and on the slider’s provenance marker), and when an override widens past a model constraint the case evaluation still tells the truth – the interpreter and the verdict panels report the violation the model states.Returns an ipywidgets
VBoxcarrying the derivation as data (theSurfaceWidgetprotocol):.panels(Panelper subview),.wiring(the printableWiringMap),.subject,.subjects(every definition the exposed cases admit),.picker(a dropdown that re-derives on change), and.swap(subject)(the same re-derivation, scriptable).- Return type: