plesty.lib.ui.plot_panel
The dockable panel that shows one Plot.
This is the whole of what the shallow design costs on the drawing side: a panel that, on every tick, polls the shared data once for all panels, asks its plot what to draw, and hands the answer to the renderer that already exists.
Two things are worth knowing about how it does that.
The data is polled once, not once per panel. Every panel of a viewer holds
the same RunData, and whichever ticks first
ingests what has committed; the rest read what is already there. That is what
replaces the old rule that each view needed a source of its own.
Items are reused by position. A drawing is a list, not a keyed mapping, so this keeps the shape it last built — the kinds, labels, colours and scales in order — and rebuilds only when that changes. A plot whose trace count grows as lines are found pays a rebuild on the tick it grows, and nothing otherwise.
Attributes
Classes
What a renderer asks about a drawing: its specs, and one by key. |
|
Sub-window showing one plot of a run. |
Functions
|
The drawing thread, started on first use. |
|
The key a drawable is addressed by: where it sits in the drawing. |
|
Return the renderer's declaration of item. |
|
Return the renderer's payload for item — its values, without its style. |
|
Return the text a drawable shows, with a scalar's unit appended. |
Module Contents
- plesty.lib.ui.plot_panel._DRAWING: concurrent.futures.ThreadPoolExecutor | None = None
- plesty.lib.ui.plot_panel._drawer() concurrent.futures.ThreadPoolExecutor
The drawing thread, started on first use.
Built lazily so importing this module still costs nothing and starts nothing — the same reason Qt is imported where it is used rather than at the top of the file.
- Return type:
concurrent.futures.ThreadPoolExecutor
- class plesty.lib.ui.plot_panel._Traces(drawing: Sequence[plesty.lib.monitor.plots.Drawable])
What a renderer asks about a drawing: its specs, and one by key.
The renderer was written against a monitor and reads only these two things from it, so this is the whole of what it needs — and the specs it reads are derived from the drawables rather than declared beside them.
Derive the specs of drawing, keyed by position.
- Parameters:
drawing (Sequence[plesty.lib.monitor.plots.Drawable])
- _specs
- _by_key
- property trace_specs: list[plesty.lib.monitor.base_monitor.TraceSpec]
Every trace, in drawing order.
- Return type:
- trace_spec(key: str) plesty.lib.monitor.base_monitor.TraceSpec
The spec of one trace.
- Parameters:
key (str) – Its positional key.
- Raises:
KeyError – If the drawing changed shape without a rebuild.
- Return type:
- plesty.lib.ui.plot_panel._key(index: int) str
The key a drawable is addressed by: where it sits in the drawing.
- Parameters:
index (int)
- Return type:
str
- plesty.lib.ui.plot_panel._spec(index: int, item: plesty.lib.monitor.plots.Drawable) plesty.lib.monitor.base_monitor.TraceSpec
Return the renderer’s declaration of item.
- Parameters:
index (int) – Its position in the drawing.
item (plesty.lib.monitor.plots.Drawable) – The drawable.
- Returns:
The spec, carrying the style the drawable brought with it.
- Return type:
- plesty.lib.ui.plot_panel._payload(item: plesty.lib.monitor.plots.Drawable) plesty.lib.monitor.base_monitor.TraceData
Return the renderer’s payload for item — its values, without its style.
- Parameters:
- Return type:
- plesty.lib.ui.plot_panel._text_of(item: plesty.lib.monitor.plots.Drawable) str | None
Return the text a drawable shows, with a scalar’s unit appended.
- Parameters:
- Return type:
Optional[str]
- class plesty.lib.ui.plot_panel.PlotPanel(plot: plesty.lib.monitor.plots.Plot, data: Any, *, theme: plesty.lib.ui.theme.Theme | None = None, **kwargs: Any)
Bases:
plesty.lib.ui.panel.PanelSub-window showing one plot of a run.
Toolkit-free until it is built, like every panel: constructing and describing it needs no GUI, which is what lets a headless test cover a viewer’s composition.
Show plot over data.
- Parameters:
plot (plesty.lib.monitor.plots.Plot) – The view to draw.
data (Any) – The run’s store, shared with this viewer’s other panels.
theme (Optional[plesty.lib.ui.theme.Theme]) – Palette for the plot;
Noneloads the packaged theme.**kwargs (Any) – Forwarded to
Panel.
- kind = 'plot'
Panel category, used for layout keys and styling hooks.
- plot
- data
- theme = None
- renderer: Any = None
- _shape: tuple[Any, Ellipsis] = ()
- _own_widget: Any = None
- _failure = ''
- _drawing: concurrent.futures.Future[list[plesty.lib.monitor.plots.Drawable]] | None = None
- build(parent: Any = None) Any
Create the widget this panel shows.
A plot that overrides
build()supplies its own widget and is never drawn as a plot — the escape hatch for a view that is a table or an image browser rather than a curve.- Parameters:
parent (Any) – The parent widget provided by the shell.
- Returns:
The widget.
- Return type:
Any
- tick() None
Show what the last draw produced, and set the next one going.
The work a draw does is not this thread’s to do. Reading what has committed and asking the plot what to draw are a file read and, for a view that fits its lines, a least-squares solve per spectrum — and this runs on the thread that answers clicks and repaints. Done here it stopped a console following a live run for seconds at a time, which is a window that looks hung while the measurement it is showing is perfectly fine.
So a tick renders whatever the drawing thread has finished and then asks it for the next, and the window is never inside a draw. A panel has at most one in flight: ticks that arrive while one is running start nothing, which is also what keeps a slow plot from queueing up work it will never catch up with. The cost is that a drawing appears on the tick after the one that asked for it — a poll interval late, on a view that is watching a measurement unfold.
- Return type:
None
- _begin_drawing() None
Ask the drawing thread for the next drawing, if it is free of this panel.
- Return type:
None
- _compute_drawing() list[plesty.lib.monitor.plots.Drawable]
Poll the data and ask the plot what to draw. Runs off the GUI thread.
The poll is shared: whichever panel gets here first brings the store up to date and the rest find it already so, which is why one run is read once however many plots watch it.
- Return type:
- _show_finished_drawing() None
Render the drawing the thread has finished, if it has finished one.
- Return type:
None
- status() str
Return what the title bar shows beside the plot’s name.
- Returns:
How far the run has got, which is the same question for every plot of it, so no plot has to answer it — or why this view stopped drawing, which is the one thing only this panel knows.
- Return type:
str
- close() None
Drop the renderer; the store is shared and is not closed here.
- Return type:
None
- describe() dict[str, Any]
Return the panel’s placement plus what it draws.
- Returns:
The panel description, with the plot’s title and class.
- Return type:
dict[str, Any]