visualdynamics.gui.panes¶
panes
¶
Self-contained view panes.
A pane owns a view, the bar of controls that belongs to it, and the state those controls carry — and nothing else. It never reaches for the project, the tree or the selection: it reports that a choice moved and lets whoever placed it decide what that means. That is what lets the same pane sit in the main window, in a dock, or in a window of its own opened from a script.
Classes:
| Name | Description |
|---|---|
DataPane |
The 2-D data view: a plot under a bar saying how to read it. |
ScenePane |
The 3-D view: the scene, its camera, and how the scene is annotated. |
Functions:
| Name | Description |
|---|---|
copy_act |
The copy act a pane's bar carries beside the selection's acts: |
image_of |
A rendered (rows, columns, 3 or 4) array of bytes as a QImage |
offer_acts |
Put the acts a selection can take on a bar, in their own fenced |
Classes¶
DataPane
¶
Bases: QWidget
The 2-D data view: a plot under a bar saying how to read it.
The bar speaks three vocabularies at once — how coherence reads, which records an FRF is filtered to, and how an FRF beside a shape set is used — and shows only what the data in front of it can actually use, because a control that is not a live option is absent rather than grayed.
The pane keeps the choice and announces it. What a choice means stays outside: filtering to the diagonal moves the tree selection, and choosing Edit Fit opens a fitting session, neither of which is a plot's business.
Methods:
| Name | Description |
|---|---|
copy_view |
What the pane shows, onto the clipboard as an image: the 3-D |
show_acts |
The acts the selection can take, on this bar ( |
offer_rms |
Show the RMS toggle for a specification on its own. |
show_spectra_views |
Offer the two-density readings, or take them away. |
show_comparison_views |
Offer the three readings, or none of them. |
show_scaling |
Show the comparison scaling, or take it away with None. |
show_srs_views |
Offer the two readings of a shock-spectrum comparison. |
show_replication_views |
Offer the two readings of a replication, or neither. |
show_events |
Offer these repeats, keeping the one already chosen. |
chosen_event |
The repeat being looked at, or None. |
step_event |
Move the event box by |
reset_plot_mode |
Back to letting the data choose. Called when the selection |
offer_waterfall |
Show the 2D/3D toggle, raised by the plain-curves path |
offer_frequency_axis |
Show the decades/hertz toggle for data drawn over frequency, |
show_quantities |
Offer a mixed object's quantity groups, keeping the choice. |
show_pages |
Offer the page stepper, or put it away for a single page. |
chosen_page |
The page on the stage, zero-based. |
chosen_quantity |
The quantity box's (dimension, hint) key, or None. |
create_waterfall_plotter |
Build the 3-D data surface, on first use. |
reserve_bottom |
Keep the bottom |
show_waterfall |
Swap the plot surface: the 2-D graphics or the 3-D view. |
component |
Which part of a complex ordinate to draw. |
show_pairs |
Offer these comparisons, keeping the one already chosen. |
chosen_pair |
The comparison being looked at, or None. |
select_pair_label |
Show the comparison this label names. True if it moved. |
step_pair |
Move to the next comparison, or the previous one. |
sync_toolbar |
The bar shows exactly when something on it does. |
show_controls |
Show exactly the controls this data can use, and hide the bar |
reset_controls |
Nothing applies until something says otherwise. |
show_pair_controls |
The bar as the fitting screen wants it: the pair choice alone. |
Attributes:
| Name | Type | Description |
|---|---|---|
showing_wavelet |
bool
|
Whether the scalogram is up — asked by whoever draws. |
showing_kurtosis |
bool
|
Whether the bar reading is up — asked by whoever draws. |
rms_wanted |
bool
|
Whether the RMS reading of a specification is asked for — |
showing_averaging |
bool
|
Is the averaging view asked for? Only meaningful for a time |
showing_filter |
bool
|
Is the filter view asked for? Only meaningful for a time |
showing_sine |
bool
|
Is the sine view asked for? Only meaningful for a time |
showing_octave |
bool
|
Is the octave-band view asked for? Only meaningful for a |
showing_truncate |
bool
|
Is the truncate view asked for? Only meaningful for a time |
showing_shocks |
bool
|
Is the shock view asked for? Only meaningful for a time |
showing_cmif |
bool
|
Is the singular-value reading asked for? Only meaningful for |
showing_waterfall |
bool
|
Is the 3-D reading asked for? Only meaningful where the |
Source code in src/visualdynamics/gui/panes.py
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 | |
Attributes¶
showing_wavelet
property
¶
Whether the scalogram is up — asked by whoever draws.
showing_kurtosis
property
¶
Whether the bar reading is up — asked by whoever draws.
rms_wanted
property
¶
Whether the RMS reading of a specification is asked for — the checked state alone, so a render can decide its panes before the bar is offered.
showing_averaging
property
¶
Is the averaging view asked for? Only meaningful for a time history, which is why the caller checks that first.
showing_filter
property
¶
Is the filter view asked for? Only meaningful for a time history, which is why the caller checks that first.
showing_sine
property
¶
Is the sine view asked for? Only meaningful for a time history beside a sweep specification, which is why the caller checks that first.
showing_octave
property
¶
Is the octave-band view asked for? Only meaningful for a plain PSD or CPSD, which is why the caller checks that first.
showing_truncate
property
¶
Is the truncate view asked for? Only meaningful for a time history, which is why the caller checks that first.
showing_shocks
property
¶
Is the shock view asked for? Only meaningful for a time history, which is why the caller checks that first.
showing_cmif
property
¶
Is the singular-value reading asked for? Only meaningful for FRFs, which is why the caller checks that first.
showing_waterfall
property
¶
Is the 3-D reading asked for? Only meaningful where the window offered it, which is why the caller checks that first.
The filter view used to outrank this and force the drawing flat — my judgment that two overlaid ribbons would occlude each other, made without drawing them. Wrong twice over (Brandon, 2026-08-25): the stage already draws paired data at one station, and a view choice that silently overrides another view choice is exactly what this interface does not do. The preview is stage geometry now, so both readings stand.
Except while the specification sheet is open: its handles
live on the flat plot, so flat_only holds the drawing flat
whatever the toggle says (Brandon, 2026-09-06).
Methods:¶
copy_view
¶
What the pane shows, onto the clipboard as an image: the 3-D
stage when it is up, the flat plot otherwise. The plot is drawn
the way the headless plots are (plot.render_image), on the
theme's own background, at the screen's pixel density, so a
retina display copies a retina image with every font at its
set size.
Source code in src/visualdynamics/gui/panes.py
show_acts
¶
The acts the selection can take, on this bar (offer_acts).
offer_rms
¶
show_spectra_views
¶
Offer the two-density readings, or take them away.
Source code in src/visualdynamics/gui/panes.py
show_comparison_views
¶
Offer the three readings, or none of them.
Only a specification with a measurement against it has three readings; anything else has one, and a chooser with one choice is a question with one answer.
Source code in src/visualdynamics/gui/panes.py
show_scaling
¶
Show the comparison scaling, or take it away with None.
The field is restated on every drawing, so setting the text must not read as the user typing it — hence the guard, the same one the pair and event boxes need for the same reason.
Source code in src/visualdynamics/gui/panes.py
show_srs_views
¶
Offer the two readings of a shock-spectrum comparison.
Source code in src/visualdynamics/gui/panes.py
show_replication_views
¶
Offer the two readings of a replication, or neither.
Only a transient specification with a record against it has them. They hide the random three while they are up: both sets are readings of "how did this compare", and a bar offering seven of those invites reading a waveform error against an abort band that does not exist.
Source code in src/visualdynamics/gui/panes.py
show_events
¶
Offer these repeats, keeping the one already chosen.
Sticky by index, unlike the channel box beside it, because a repeat is its index — the third playing of the waveform is the third whatever else the record holds — where a channel is a DOF that may arrive or leave.
No repeat is marked out. Which one is the bad one depends on which reading you care about and on what the article is for, and naming one here would be putting a judgment in a list of facts — the numbers beside the plot are what to decide with.
Source code in src/visualdynamics/gui/panes.py
chosen_event
¶
step_event
¶
Move the event box by step, stopping at either end.
Stopping rather than wrapping: the repeats are in time order, and running off the last one back to the first would read as having gone forwards.
Source code in src/visualdynamics/gui/panes.py
reset_plot_mode
¶
Back to letting the data choose. Called when the selection changes, so an override applies to the thing being looked at and not for ever.
offer_waterfall
¶
Show the 2D/3D toggle, raised by the plain-curves path
itself, like show_pairs: show_controls runs before the
window knows whether this drawing ends as plain curves.
Offered whenever the current reading has both forms, and withheld only where one of them does not exist — the kurtosis bars are a flat picture and a depth axis would have nothing to put along it. That is the setting half of principle 3, and the half that survives: it is the readings that stay offered whichever one is chosen (Brandon, 2026-08-27).
The scalogram has both, and opens in 3-D: it is already a function of two variables, so a surface is its natural form.
Source code in src/visualdynamics/gui/panes.py
offer_frequency_axis
¶
Show the decades/hertz toggle for data drawn over frequency,
reading log, the axis as it stands — the class's convention
until the viewer chooses (core.data.frequency_axis).
Source code in src/visualdynamics/gui/panes.py
show_quantities
¶
Offer a mixed object's quantity groups, keeping the choice.
entries is [(label, key)], largest group first — index 0 is
the default the waterfall draws unasked. Sticky by key, not by
position, like the pair box: the list is rebuilt on every
drawing, and a choice that moved with the index would jump to
another quantity whenever a record pick changed the counts.
Hidden below two entries — one quantity is not a choice.
Source code in src/visualdynamics/gui/panes.py
show_pages
¶
Offer the page stepper, or put it away for a single page.
page is zero-based, as the scene counts them; the box shows
one-based with the total as its suffix, so it reads
[<] 2 / 3 [>]. Restated on every drawing, so the guard keeps
that from reading as the user turning a page.
Source code in src/visualdynamics/gui/panes.py
chosen_page
¶
chosen_quantity
¶
create_waterfall_plotter
¶
Build the 3-D data surface, on first use.
The same deferral as ScenePane.create_plotter and for the
same macOS reason — and safe here without a callback, because
the only thing that asks for it is a toggle on this pane's own
bar, which cannot be clicked before the pane is on screen.
Returns the plotter, or None when it was already built.
Source code in src/visualdynamics/gui/panes.py
reserve_bottom
¶
Keep the bottom pixels of the plot area empty.
The console tab floats over the views' bottom edge rather than
claiming a strip, and it landed on the legend row and the
bottom axis (Brandon, 2026-09-01). A layout margin is the
clearance: every plot, legend and axis ends above it, and the
margin survives clear(), so one call at construction holds.
Source code in src/visualdynamics/gui/panes.py
show_waterfall
¶
Swap the plot surface: the 2-D graphics or the 3-D view.
Both stay children of the pane; only visibility moves, so the toggle costs no layout work and the hidden one keeps its state.
Source code in src/visualdynamics/gui/panes.py
component
¶
show_pairs
¶
Offer these comparisons, keeping the one already chosen.
Sticky by DOF and not by position: the list is rebuilt on every drawing, and a selection that moved with the index would jump to another channel whenever one arrived or left.
This raises the bar itself, and has to. show_controls decides
whether there is a bar from the controls it knows about, and
it runs before this does — so a drop-down put up afterwards
landed in a bar that had already been hidden. It went unnoticed
because a specification used to be complex, which offered the
component box, which kept the bar up for its own reasons;
storing PSDs real took that away and the drop-down went with it.
A QAction's isVisible is its own flag and stays true inside a
hidden toolbar, so anything checking that alone will agree the
box is up while the screen shows nothing.
Source code in src/visualdynamics/gui/panes.py
chosen_pair
¶
select_pair_label
¶
Show the comparison this label names. True if it moved.
By label rather than by DOF pair, because the table names its rows the way the box does and matching the text is what keeps the two agreeing without either learning the other's model.
Source code in src/visualdynamics/gui/panes.py
step_pair
¶
Move to the next comparison, or the previous one.
Stops at the ends rather than wrapping: running off the bottom of a channel list and arriving back at the top reads as nothing having happened.
Source code in src/visualdynamics/gui/panes.py
sync_toolbar
¶
The bar shows exactly when something on it does.
Derived, never decided by a caller. Five methods put controls
on this bar and each knows only its own slice, so any one of
them setting the bar's visibility from its own slice hides
another's controls — which is exactly what happened: the
fitting screen's show_pair_controls hid the whole bar
whenever no shape set was co-selected, and once Residual moved
onto that bar, a fit started from the FRF's own act lost
it. An action's isVisible is its own property and does not
follow the bar's, so the bar can be read back off its contents.
The dividers settle first and are then discounted: a separator
is visible whether or not anything is around it, so a bar of
nothing but dividers passes a plain any(isVisible) and stays
up — which is what the first fenced group did.
Source code in src/visualdynamics/gui/panes.py
show_controls
¶
show_controls(*, map_wanted: bool | None, diagonal: tuple[str, str, bool] | None, cmif: bool, complex_data: bool, pair: bool, averaging: bool = False, shocks: bool = False, residual: bool = False, octave: bool = False, sine: bool = False) -> None
Show exactly the controls this data can use, and hide the bar when that is none of them.
map_wanted is True for a map, False for curves and None when
the data has no such choice; diagonal is None when there is no
diagonal to filter to, else (label, tooltip, already_filtered);
cmif offers the singular-value reading; complex_data offers
the component box; pair offers Edit Fit / Resynthesis;
averaging offers the frames a time history would be cut into.
Source code in src/visualdynamics/gui/panes.py
1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 | |
reset_controls
¶
Nothing applies until something says otherwise.
Called before every render, so a drawing that has no use for the bar — photos, a report — does not have to remember to put away the controls the last one left up.
Which is a promise each control has to be registered here to keep. The event box was added later and never was, so once a transient comparison raised it, it stayed up over the record on its own — where every event is on screen at once and there is nothing to choose between — and over a channel table, which has no events at all.
Source code in src/visualdynamics/gui/panes.py
show_pair_controls
¶
The bar as the fitting screen wants it: the pair choice alone.
Source code in src/visualdynamics/gui/panes.py
ScenePane
¶
Bases: QWidget
The 3-D view: the scene, its camera, and how the scene is annotated.
What is in the scene stays outside — geometry, deflection and the picking that edits them all need the project, and none of them is a view's business. The pane owns the render window, the annotations drawn around whatever is in it, and the bar those annotations hang from. Anyone placing the pane can add their own actions to that bar.
Methods:
| Name | Description |
|---|---|
copy_view |
The 3-D view as it stands, onto the clipboard as an image. |
show_acts |
The acts the selection can take, on this bar ( |
offer_rigid |
Show the toggle only while it applies — one whole geometry, |
create_plotter |
Build the embedded VTK view, once the pane is on screen. |
set_home_view |
The view Reset View returns to, and the geometry it is |
frame |
Fit new content. Turned to the home view when its geometry is |
reset_view |
Turn the camera to the home view and fit the scene. |
set_bounds_visible |
Toggle the labeled axes drawn around the geometry. |
set_orientation_visible |
Toggle the orientation triad in the corner. |
apply_annotations |
Re-apply annotations in place, so the camera keeps its position. |
apply_background |
An empty 3D view must match the theme, not VTK's white default. |
Attributes:
| Name | Type | Description |
|---|---|---|
showing_rigid |
bool
|
Whether the rigid-body reading is up. |
Source code in src/visualdynamics/gui/panes.py
Attributes¶
Methods:¶
copy_view
¶
The 3-D view as it stands, onto the clipboard as an image.
Source code in src/visualdynamics/gui/panes.py
show_acts
¶
The acts the selection can take, on this bar (offer_acts).
offer_rigid
¶
Show the toggle only while it applies — one whole geometry, nothing riding it — checked if it was wanted last time.
Source code in src/visualdynamics/gui/panes.py
create_plotter
¶
Build the embedded VTK view, once the pane is on screen.
Returns the plotter, or None if it was already built — the caller usually wants to draw into a view that has just appeared.
Source code in src/visualdynamics/gui/panes.py
set_home_view
¶
The view Reset View returns to, and the geometry it is
owner's; None hides it (a scene with no geometry in it has no
view of its own to return to).
Source code in src/visualdynamics/gui/panes.py
frame
¶
Fit new content. Turned to the home view when its geometry is new to the pane; otherwise only refitted, so a turn the user made survives stepping from a geometry to the shapes drawn on it — framing is for new content, and the view belongs to the user.
Source code in src/visualdynamics/gui/panes.py
reset_view
¶
Turn the camera to the home view and fit the scene.
Source code in src/visualdynamics/gui/panes.py
set_bounds_visible
¶
set_orientation_visible
¶
apply_annotations
¶
Re-apply annotations in place, so the camera keeps its position.
Source code in src/visualdynamics/gui/panes.py
apply_background
¶
An empty 3D view must match the theme, not VTK's white default.
Source code in src/visualdynamics/gui/panes.py
Functions:¶
copy_act
¶
The copy act a pane's bar carries beside the selection's acts: what the pane shows, onto the clipboard as an image (Brandon, 2026-09-24: every plot, table and figure should copy like a chat's code blocks do). An act rather than a standing control, because the bar shows exactly when something on it applies, and a copy applies exactly when something is drawn. One glyph and one tooltip shape on both bars, so it reads as the same act.
Source code in src/visualdynamics/gui/panes.py
image_of
¶
A rendered (rows, columns, 3 or 4) array of bytes as a QImage that owns its memory — the array a screenshot hands back is freed with it, and a QImage over it would read garbage.
Source code in src/visualdynamics/gui/panes.py
offer_acts
¶
Put the acts a selection can take on a bar, in their own fenced group at its end — an icon each, like every other button on a bar, the verb and its meaning in the tooltip (Brandon, 2026-09-12: "none should [carry text] and the user should rely on tool tips to learn icons they don't recognize"; this reverses the labeled buttons of 2026-09-04). Every act on the bar, none behind a menu.
acts is [(verb, label, icon name, callback, tooltip)], in the
order the bar shows them. Rebuilt on every call: a toolbar cannot
reorder its actions, and the order is part of the reading — the
same verb in the same place whatever else the selection allows.