visualdynamics.viz.animate¶
animate
¶
Moving a geometry scene without rebuilding it.
The scene's meshes all share one point buffer (shared_points), so a
frame is three steps: compute the offsets of the moving nodes, write
them through a numpy view of VTK's memory, and mark the buffer modified.
Nothing is allocated or rebuilt per frame, which is what allows large
models to be animated.
The animators use no Qt; the caller drives them. The animate_*
functions play an animation in a window, or save a still or an MP4.
Classes:
| Name | Description |
|---|---|
PairedAnimator |
Two animated copies, moving in step. |
GeometryAnimator |
A geometry scene whose nodes move with a deflection. |
EnvelopeAnimator |
One copy of a PSD envelope. The envelope is drawn as a pair of |
Functions:
| Name | Description |
|---|---|
cycle_parameters |
The phases, in radians, that a saved mode-shape animation steps |
sweep_parameters |
The sample (or line) indices a saved sweep steps through: 0 to |
movie_frames |
Yield the scene rendered at each of |
build_pair |
Two (geometry, deflection) copies moving in step in one scene, |
pair_deflections |
The two (geometry, deflection) copies of an overlaid pair: mode |
animate_pair |
Two deflections overlaid and moving together, as the window |
animate_shape |
One mode shape (index |
animate_envelope |
A PSD's envelope on a geometry, as the app shows it: two copies |
animate_ods |
The operating deflection shape of complex spectra at one line, as |
animate_time |
Time records moving on a geometry, as the app plays them: the |
Classes¶
PairedAnimator
¶
PairedAnimator(first: GeometryAnimator, second: GeometryAnimator)
Two animated copies, moving in step.
Each copy is a GeometryAnimator with its own point buffer and its
own automatic scale, so two mode shapes with different
normalizations are compared by shape, which is the purpose of
overlaying them. The copies may be on the same geometry or on two.
Methods:
| Name | Description |
|---|---|
set_scale |
Set both copies' scale, as a multiple of each one's own |
set_parameter |
Move both copies to this phase or index. |
follow |
Move a mesh drawn at nodes with the first copy: the + |
render |
Render the scene the copies share. |
reset |
Put both copies back at their undeformed positions. |
Attributes:
| Name | Type | Description |
|---|---|---|
deflection |
Any
|
The first copy's deflection, which for a pair sharing one |
parameter |
float
|
The first copy's current phase or index. |
Source code in src/visualdynamics/viz/animate.py
Attributes¶
deflection
property
¶
The first copy's deflection, which for a pair sharing one deflection (the envelope) is the pair's.
Methods:¶
set_scale
¶
Set both copies' scale, as a multiple of each one's own automatic scale.
set_parameter
¶
follow
¶
Move a mesh drawn at nodes with the first copy: the + deflection of an envelope, the first set of a comparison.
render
¶
GeometryAnimator
¶
GeometryAnimator(plotter: Any, geometry: Geometry, deflection: Deflection, unit_system: UnitSystem | None = None, fraction: float = 0.1, colormap: bool = False, clim: tuple[float, float] | None = None, scalar_name: str = 'displacement', **draw: Any)
A geometry scene whose nodes move with a deflection.
The geometry is drawn into plotter on construction (add_geometry,
with any extra keyword arguments passed on). deflection supplies
offsets for the nodes it moves, and every other node stays at its
base position. The parameter is a phase in radians for a mode shape,
and a sample index for time data.
The automatic scale makes the largest deflection fraction of the
model's size (the diagonal of its bounding box), and set_scale
multiplies it. With colormap the nodes are colored by the size of
their offset, under the array name scalar_name, on a color range
of clim; by default the range runs from zero to the largest offset
any node ever reaches, fixed for the whole animation.
Methods:
| Name | Description |
|---|---|
follow |
Move a mesh drawn at nodes with those nodes from now on: a |
set_scale |
Set the user's scale, a multiple of the automatic one, and |
set_parameter |
Place the nodes for this phase or sample index. |
render |
Render the plotter. |
reset |
Put every node back at its base position, and its color at |
Attributes:
| Name | Type | Description |
|---|---|---|
scale |
float
|
The factor offsets are drawn at: the automatic scale times the |
Source code in src/visualdynamics/viz/animate.py
Attributes¶
scale
property
¶
The factor offsets are drawn at: the automatic scale times the user's.
Methods:¶
follow
¶
Move a mesh drawn at nodes with those nodes from now on: a
viz.sensors.SensorMesh, or anything with its node_rows,
base, points and view. Each point keeps its offset from its
node, so a body translates with its node and keeps its
orientation.
Source code in src/visualdynamics/viz/animate.py
set_scale
¶
Set the user's scale, a multiple of the automatic one, and redraw at the current parameter.
set_parameter
¶
Place the nodes for this phase or sample index.
Source code in src/visualdynamics/viz/animate.py
render
¶
reset
¶
Put every node back at its base position, and its color at zero.
Source code in src/visualdynamics/viz/animate.py
EnvelopeAnimator
¶
EnvelopeAnimator(plotter: Any, geometry: Geometry, deflection: Any, sign: float = 1.0, **kwargs: Any)
Bases: GeometryAnimator
One copy of a PSD envelope. The envelope is drawn as a pair of these, one deflected + and one -.
sign (+1 or -1) multiplies the scale, so the window's one Scale
control still drives both copies through PairedAnimator. The
parameter is the abscissa line, since an envelope has no phase to
sweep. Color is absolute: dB below the loudest node at any line,
between the deflection's FLOOR_DB and 0. Every line deflects at
full size, so the color is the only thing that shows level; a node
with no data is drawn at the floor.
Methods:
| Name | Description |
|---|---|
set_parameter |
Move to this abscissa line, and recolor the nodes for it. |
Attributes:
| Name | Type | Description |
|---|---|---|
scale |
float
|
The automatic scale times the user's, times |
Source code in src/visualdynamics/viz/animate.py
Attributes¶
Methods:¶
set_parameter
¶
Move to this abscissa line, and recolor the nodes for it.
Source code in src/visualdynamics/viz/animate.py
Functions:¶
cycle_parameters
¶
cycle_parameters(cycle_seconds: float = SECONDS_PER_CYCLE, fps: int = MOVIE_FPS, seconds: float = MOVIE_SECONDS) -> ndarray
The phases, in radians, that a saved mode-shape animation steps through.
Whole cycles lasting at least seconds in total, at fps frames a
second and at the speed the window plays (cycle_seconds a cycle).
The last frame stops one step short of 2π, so a player set to loop
shows no repeated frame where the file wraps.
Source code in src/visualdynamics/viz/animate.py
sweep_parameters
¶
The sample (or line) indices a saved sweep steps through: 0 to
count - 1, once, in seconds at fps frames a second, the way the
window plays a record. Indices are spaced evenly, so some are skipped
when there are more of them than frames, and some repeat when there
are fewer.
Source code in src/visualdynamics/viz/animate.py
movie_frames
¶
Yield the scene rendered at each of parameters, as images: the
frames of a movie, one at a time. step(parameter) moves the scene
there; it is an animator's set_parameter, or a function that also
moves whatever else goes with it (a caption, the window's plot
cursor).
Source code in src/visualdynamics/viz/animate.py
build_pair
¶
build_pair(plotter: Any, first: tuple[Geometry, Any], second: tuple[Geometry, Any], *, colors: tuple[str | None, str | None], alphas: tuple[float, float], unit_system: UnitSystem | None = None, text_color: str = '#000000') -> PairedAnimator
Two (geometry, deflection) copies moving in step in one scene,
each on its own meshes in one flat color (colors, None for the
geometry's own colors) at its own opacity (alphas). This is the
overlay that the window, the report and animate_pair all show.
Source code in src/visualdynamics/viz/animate.py
pair_deflections
¶
pair_deflections(a: ShapeSet, i: int, b: ShapeSet, j: int, a_geometry: Geometry, b_geometry: Geometry, projected: ShapeSet | None = None, on_basis: bool = False) -> tuple[tuple, tuple]
The two (geometry, deflection) copies of an overlaid pair: mode
i of a on a's geometry, and mode j of b, phase-aligned to it
(paired_mode), on b's geometry. With on_basis, the second copy
is instead the projection of b drawn on a's geometry, both sampled
at the basis DOFs (this needs projected). projected is b carried
onto a's DOFs, and is needed when the two geometries differ.
Source code in src/visualdynamics/viz/animate.py
animate_pair
¶
animate_pair(first: tuple[Geometry, Any], second: tuple[Geometry, Any], *, colors: tuple[str | None, str | None] | None = None, alphas: tuple[float, float] | None = None, caption: str = '', unit_system: UnitSystem | None = None, scale: float = 1.0, cycle_seconds: float = SECONDS_PER_CYCLE, theme: Any = None, screenshot: str | None = None, movie: str | None = None, show: bool = True) -> Any
Two deflections overlaid and moving together, as the window
animates a picked MAC cell. pair_deflections makes the pair.
Each copy is scaled to its own peak, so the picture compares shape
and not level. caption, when given, is written in the corner of
every frame; core.shapes.pair_caption makes one that includes a
note on the two scales.
colors default to the theme's pair, and alphas to the first
copy solid and the second translucent (theme.overlay_alphas).
scale multiplies both automatic scales, and cycle_seconds is the
time of one cycle. screenshot saves the still at peak phase, and
movie saves whole cycles as an MP4 and returns its path; otherwise
a window plays it and is returned.
Source code in src/visualdynamics/viz/animate.py
animate_shape
¶
animate_shape(geometry: Geometry, shapes: ShapeSet, mode: int = 0, *, unit_system: UnitSystem | None = None, scale: float = 1.0, colormap: bool = True, cycle_seconds: float = SECONDS_PER_CYCLE, theme: Any = None, screenshot: str | None = None, movie: str | None = None, show: bool = True, sensors: Any = None, sensor_size: float = 1.0) -> Any
One mode shape (index mode of shapes) moving on a geometry, as
the app animates it.
With colormap the nodes are colored by displacement on viridis, as
in the app's scene. scale multiplies the automatic scale. With
screenshot the deflected shape is rendered to the file at peak
phase, the frame that shows the shape best. With movie it is saved
as an MP4 (H.264) of whole cycles at cycle_seconds a cycle, and
the path is returned (gui.movie.write_movie). Otherwise a window
plays it and is returned.
With sensors, a channel table, the sensors it places are drawn at
their nodes and move with them (viz.sensors), sensor_size times
true size.
Source code in src/visualdynamics/viz/animate.py
animate_envelope
¶
animate_envelope(geometry: Geometry, data: Any, records: Any = None, *, frequency: float | None = None, quantity: str | None = None, unit_system: UnitSystem | None = None, scale: float = 1.0, colormap: bool = True, seconds: float = SECONDS_PER_RECORD, theme: Any = None, screenshot: str | None = None, movie: str | None = None, show: bool = True, sensors: Any = None, sensor_size: float = 1.0) -> Any
A PSD's envelope on a geometry, as the app shows it: two copies deflected by plus and minus sqrt(PSD) at one line, colored in dB below the loudest node.
One quantity at a time, because newtons and meters per second
squared cannot share a normalization; by default the most common
one among the records. Cross records are left out, since their
phase belongs to an operating deflection shape and not an envelope.
The still is at frequency (the first line at or above it), or at
the strongest line when none is given.
screenshot saves the still. movie sweeps every line once in
seconds, as Play does in the window, with the line's frequency
written on each frame, and returns the path. Otherwise a window
plays it and is returned.
Raises ValueError when no auto record measures the quantity, or when none of the records is at a node of this geometry.
With sensors, a channel table, the sensors it places are drawn at
their nodes and move with them (viz.sensors), sensor_size times
true size.
Source code in src/visualdynamics/viz/animate.py
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 | |
animate_ods
¶
animate_ods(geometry: Geometry, data: Any, records: Any = None, *, frequency: float | None = None, quantity: str | None = None, unit_system: UnitSystem | None = None, scale: float = 1.0, colormap: bool = True, cycle_seconds: float = SECONDS_PER_CYCLE, theme: Any = None, screenshot: str | None = None, movie: str | None = None, show: bool = True, sensors: Any = None, sensor_size: float = 1.0) -> Any
The operating deflection shape of complex spectra at one line, as the app animates it when the object is selected with a geometry.
The shape is the records' complex values at frequency (the first
line at or above it), or at the strongest line when none is given,
swept in phase like a complex mode. One quantity at a time, as
the envelope is, by default the most common one among the
records (quantity_records). The records follow
animation_records: one record per DOF, and the first reference of a
whole FRF. screenshot and movie save it as animate_shape does,
and otherwise a window plays it.
Raises ValueError for real data, which has no phase, when no record measures the quantity, and when none of the records is at a node of this geometry.
With sensors, a channel table, the sensors it places are drawn at
their nodes and move with them (viz.sensors), sensor_size times
true size.
Source code in src/visualdynamics/viz/animate.py
animate_time
¶
animate_time(geometry: Geometry, data: Any, records: Any = None, *, quantity: str | None = None, shapes: Any = None, unit_system: UnitSystem | None = None, scale: float = 1.0, colormap: bool = True, seconds: float = SECONDS_PER_RECORD, theme: Any = None, screenshot: str | None = None, movie: str | None = None, show: bool = True, sensors: Any = None, sensor_size: float = 1.0) -> Any
Time records moving on a geometry, as the app plays them: the
record once through in seconds, one record per DOF
(animation_records) and one quantity, by default the most common
one among the records (quantity_records). A window plays it on
a loop.
With screenshot the still is the sample where some record is
furthest from zero, because the first sample is usually at rest and
a still of the structure at rest shows nothing. With movie the
record is saved once through as an MP4 (H.264) and the path is
returned.
With shapes, a shape set, the records played are the modal
coordinates of that set (M1 … Mn, such as the modal responses
computed from forces), and each moves the geometry by its mode's
shape scaled by its value at each sample (deform.modal_deflection):
the physical response is never formed, so a large model plays at the
cost of its modes rather than of a record per DOF. Several modes play
as their sum; a pick of some of them plays their contribution.
Raises ValueError when no record measures the quantity, or none of the records is at a node of this geometry.
With sensors, a channel table, the sensors it places are drawn at
their nodes and move with them (viz.sensors), sensor_size times
true size.
Source code in src/visualdynamics/viz/animate.py
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 | |