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 |
|---|---|
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 greyed.
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 |
|---|---|
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 overlay/ratio pair, or take it 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_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
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 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 | |
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_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 judgement 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:¶
show_acts
¶
The acts the selection can take, on this bar (offer_acts).
offer_rms
¶
show_spectra_views
¶
Offer the overlay/ratio pair, or take it 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 judgement 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,
) -> 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
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 | |
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 |
|---|---|
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_bounds_visible |
Toggle the labelled 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:¶
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_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:¶
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 labelled 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.