visualdynamics.viz.marks¶
marks
¶
Averaging frames and shock windows on the waterfall stage.
The 3-D counterpart of plot/averaging.py and plot/shocks.py: the
same numbers — Averaging.frame_bounds, .levels, window_shape,
the shocks' own windows — drawn as stage geometry instead of plot
items, so the two views cannot disagree about where a frame is.
Read-only on purpose (Brandon, 2026-08-23): the side panel is the editor in both views, and the 2-D overlays keep their drag handles. A span edge here is a translucent plane where the flat plot draws a draggable line; the window rail draws on the back wall, above the stage ceiling, because every channel shares one time axis — one rail serves all of them, exactly as it does in 2-D.
Kept free of Qt, like the rest of viz.
Functions:
| Name | Description |
|---|---|
averaging_stage_geometry |
The averaging as plain stage geometry — no VTK, no Qt. |
shock_stage_geometry |
Each event's analysis window as plain stage geometry — the |
add_averaging_marks |
The averaging as stage geometry: the span, bands, windows. |
add_truncation_marks |
The truncation as stage geometry: the discarded ends greyed, |
add_shock_marks |
Each event's analysis window as a translucent slab, numbered. |
add_filter_preview |
The low-pass previewed on the stage: each record's filtered |
decade_labels |
The decades inside a log10 range, each with the label the 2-D |
add_decade_axis |
The frequency axis in decades, drawn the way the 2-D plot |
add_octave_preview |
The banded conversion previewed on the stage: each drawn |
Classes¶
Functions:¶
averaging_stage_geometry
¶
averaging_stage_geometry(
averaging: Averaging,
sample_rate: float,
extents: Sequence[float],
) -> dict[str, Any]
The averaging as plain stage geometry — no VTK, no Qt.
The numbers add_averaging_marks puts into a plotter and the
report's canvas figure draws for itself: the analysed span, and
per frame the rail's baseline, the window's sampled weights, the
glyph height at each and the two end caps. Extracted so the two
views cannot disagree about where a frame is, which is the whole
reason this module exists.
Everything is in stage coordinates already — x across, wall for
the back wall the rail draws on, z up.
Source code in src/visualdynamics/viz/marks.py
shock_stage_geometry
¶
Each event's analysis window as plain stage geometry — the
slab's span and the number it wears. The 3-D counterpart of
plot/shocks.py's regions, shared by the app's stage and the
report's canvas the way the averaging's geometry is.
Source code in src/visualdynamics/viz/marks.py
add_averaging_marks
¶
add_averaging_marks(
plotter: Any,
averaging: Averaging,
sample_rate: float,
extents: Sequence[float],
theme: Any = None,
) -> dict[str, int]
The averaging as stage geometry: the span, bands, windows.
The analysis span is one filled slab with rimmed edges — the same
reading as a shock's window, because both answer 'which stretch of
the record is analysed' (Brandon, 2026-08-24; two lone edge
planes read as different objects). Returns counts a test can
hold: frames drawn on the rail and edges (always two —
the span's start and stop rims).
Source code in src/visualdynamics/viz/marks.py
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | |
add_truncation_marks
¶
add_truncation_marks(
plotter: Any,
truncation: Any,
first: float,
last: float,
extents: Sequence[float],
theme: Any = None,
) -> dict[str, int]
The truncation as stage geometry: the discarded ends greyed, the kept stretch clear, handles on its edges.
The greying is a slab over each end that will be cut — grey
because cut-away data is reference, not subject, the flat
overlay's own reading — with a rim at each cut instant and the
span-editing handles on the kept stretch (_handles, the same
resize-move-resize grammar as the averaging slab). Returns the
rim count a test can hold.
Source code in src/visualdynamics/viz/marks.py
add_shock_marks
¶
add_shock_marks(
plotter: Any,
shocks: Sequence[Any],
extents: Sequence[float],
theme: Any = None,
locked: bool = False,
) -> dict[str, int]
Each event's analysis window as a translucent slab, numbered.
The flat plot brackets a window with a region; here the bracket
has depth — the slab spans every channel, because the window does.
locked leaves the grab handles off, exactly as the 2-D regions
go immovable: a record the controller already cut into frames is
not the user's to re-window.
Source code in src/visualdynamics/viz/marks.py
add_filter_preview
¶
add_filter_preview(
plotter: Any,
arrays: dict[str, Any],
extents: Sequence[float],
stations: int,
theme: Any = None,
) -> dict[str, int]
The low-pass previewed on the stage: each record's filtered twin, drawn over the raw ribbon at that record's own station.
The filtered data is what carries the colour — the level
colormap, exactly as an unfiltered stage draws — and the raw
record stands back in grey behind it (add_waterfall's color).
That is the way round the paired stage already reads: the thing
being decided takes the ink and its reference stands back. The
first pass here had it inverted, raw in viridis and the twin in
one flat colour, which asked the reader to judge the filtered
record from the drabber of the two lines (Brandon, 2026-08-25).
Normalized against the raw stage's own extents, passed in
rather than recomputed, which is the whole of the correctness
here: the filtered curves come from a second waterfall_arrays
call and would otherwise be scaled to their own range — a
filtered record is quieter than its raw one, so it would draw
stretched to the same height as what it is being compared against
and the comparison would say nothing. The banded stage taught
this the hard way (Brandon, 2026-08-25): two things drawn
together must be normalized together. The colour scale is pinned
to those extents for the same reason, so a level means the same
height and the same hue whichever ribbon it is on.
stations is how many the raw stage laid out, so the twins land
at the same depths even when the filter drops a record's every
sample to a gap.
Source code in src/visualdynamics/viz/marks.py
decade_labels
¶
The decades inside a log10 range, each with the label the 2-D
plot gives it: 1 for 10⁰, 10¹, 10² … otherwise.
Source code in src/visualdynamics/viz/marks.py
add_decade_axis
¶
The frequency axis in decades, drawn the way the 2-D plot draws it: a grid line and a label at every power of ten, and nothing at the even divisions of the range.
The cube axes can only label even divisions of a range — asked
for a log axis they printed the exponents at −0.6, 0.45, 1.5 …,
which matched nothing on the flat plot (Brandon, 2026-09-05). So
their frequency labels, ticks and grid lines are stood down and
the decades go on as stage geometry: a line up the back wall and
across the floor at each, the label under the front edge, exactly
as the depth axis already carries the channel names instead of
numbers. extents are the stage's (x0, x1, z0, z1) in log10.
Returns the labels drawn, for the tests and the status line.
Source code in src/visualdynamics/viz/marks.py
add_octave_preview
¶
add_octave_preview(
plotter: Any,
curves: Sequence[tuple[Any, Any]],
extents: Sequence[float],
stations: int,
theme: Any = None,
) -> dict[str, int]
The banded conversion previewed on the stage: each drawn record's steps at that record's own station, in the preview colour the flat plot uses — one flat colour, because the steps are a proposal over the data rather than data.
curves is one (x, z) pair per drawn record, already in the
stage's own reading (log10 where the axes are), and the
normalization is against the raw stage's extents — the filter
preview's rule: two things drawn together are normalized together.