Viz¶
Visualization of solved results: field lines, the field-display models and the render targets a viewer draws.
femforge.viz
¶
Visualization of solved results: field-line rendering, the field-display models and the composable render targets a viewer draws from a case.vtu.
Modules:
-
colormaps–ParaView's colormap presets, registered with matplotlib so every colormap name resolves through pyvista.
-
field_display–Field display state for a solved run: which array is colored, how it reduces to a scalar, and the color range that follows; pyvista is imported lazily inside the render half.
-
field_lines–3D magnetic field lines from a solved Elmer
case.vtu: streamlines seeded through the domain and colored by|B|. -
scene–Composable render targets: a
Scenedraws severalRenderables in one plotter refresh, on the plotter thread.
Classes:
-
FieldLines–A
Renderablefor the solved B-field streamlines of onecase.vtu. -
FieldLineOptions–Typed options for the 3D field-line render.
-
SeedPlacement–Where the streamline seed points are placed within the domain bounding box.
-
Colormap–Perceptually-uniform matplotlib colormaps for the
|B|magnitude scale. -
OpacityTransfer–A pyvista opacity transfer function that maps the
|B|scalar to per-element opacity; the_rvariants reverse the ramp. -
InterpolatorType–The cell-location strategy the streamline integrator uses (pyvista's
interpolator_type). -
StreamlineActor–The plotter actor names
draw_streamlinesregisters, so toggling the overlay off is a singleremove_actor. -
StreamlineActors–The precomputed drawables for a field-line view, split from plotting so the expensive part runs off the UI thread.
-
Association–Whether a VTU array lives on mesh points or cells (pyvista's
preference). -
BodyPaint–Where a body's color comes from.
-
BodyStyle–A body's own look: where its color comes from, a solid color when it has one, and its opacity.
-
DisplayMode–How a field array is reduced to the value that drives the color.
-
DisplaySpec–The complete, serializable state of one field display: which array is colored, how it reduces, and how the colors map.
-
FieldInfo–One displayable VTU array: where it lives, how wide it is, and which display modes it supports.
-
FieldScene–One run's solved bodies as a recolorable field display.
-
SceneActor–The plotter actor names a
FieldSceneregisters, so a toggle removes exactly one. -
Renderable–Something a workbench run returns for display: it draws itself into
plotter(on the plotter thread). -
Scene–An ordered group of
Renderables drawn into one plotter refresh: clear once, draw in order (later items on top), repaint once.
Functions:
-
select_flux_density_array–Pick the B array from a VTU's array names: the nodal form first (no cell→point projection needed), then the elemental
"... e", then any name containing the phrase (case-insensitive). -
seed_points–The
(N, 3)streamline seed coordinates for the domainboundsandoptions(pure Python — unit-testable without a render context). -
build_streamlines–Seed and integrate |B| streamlines through a dataset that already carries B as point data, without touching a plotter.
-
build_streamlines_from_vtu–Read a solved
case.vtuand integrate its B-field streamlines into a drawableStreamlineActors— no plotter touched, safe off the UI thread. -
prepare_streamline_source–Narrow a read grid to the integration region and put B on its points, returning the dataset and the B array name — the read-independent half of
build_streamlines_from_vtu. -
draw_streamlines–Draw a precomputed
StreamlineActorsintoplotterwithout clearing or showing it, so it composes inside aScene. -
render_streamlines–One-shot: build streamlines through
datasetand draw them, in a plotter of its own whenplotteris None. -
render_field_lines–Render the magnetic flux-density field lines from a solved
case.vtu, headless to a PNG or in an interactive window. -
field_infos–Every displayable array of a VTU as a
FieldInfo,GeometryIdsexcluded, sorted by display name. -
reduce_field–The scalar a display mode draws from one field array.
-
polar_angle–Each vector's XY direction as a cyclic coordinate in
[0, 1]—atan2(y, x)mapped off[-pi, pi]. -
polar_rgba–Per-vector RGBA for
DisplayMode.POLAR_XY: hue from the XY angle through a cycliccmap, brightness and alpha from the sigmoid-scaled XY magnitude. -
color_range–The
(lo, hi)color limits spanning every scalar chunk's own range, from the finite values only; an empty selection gives(0.0, 1.0). -
camera_needs_reset–Whether the camera has lost the model, with the box behind it or outside its view cone; a camera inside the box always keeps its view.
-
plotly_colorscale–A plotly colorscale from sampled RGB(A) rows: evenly-spaced stops paired with
"rgb(r,g,b)"strings. -
log_colorbar_ticks–Decade tick positions spanning a log color range, with their
1e-notation labels. -
mesh3d_traces–One plotly
Mesh3dtrace as a plain JSON dict: a body's triangulated surface colored byintensity, or bycoloralone. -
outline_traces–One plotly
Scatter3dlines trace drawing every(N, 2, 3)segment, NaN-separated so the segments stay disjoint. -
list_fields–Every displayable field of a VTU grid (
GeometryIdsexcluded), sorted by display name. -
split_by_body–The grid split into one block per named body, keyed by its
entities.jsonname via theGeometryIdscell array. -
feature_outline–The feature and boundary edges of a multiblock's outer surface — the black wireframe drawn over the field, the body outlines on a 2D slice — or None when the surface has none.
-
model_dim_of–2 for a flat (axisymmetric slice) grid with no Z extent, else 3.
-
sample_colormap–countevenly-spaced RGBA rows from a named colormap, resolved through pyvista'sget_cmap_safe. -
surface_triangles–A block's outer surface as
(points, triangles): an(N, 3)coordinate array and an(M, 3)vertex-index array. -
outline_segments–The feature edges as an
(N, 2, 3)array of line segments.
Attributes:
-
Bounds–A pyvista axis-aligned bounding box, as
(xmin, xmax, ymin, ymax, zmin, zmax). -
Point3–One 3D seed coordinate, as
(x, y, z). -
FLUX_DENSITY–The MagnetoDynamicsCalcFields name for B in its nodal form; the elemental form the solver writes by default appends
" e". -
FIELD_RENAMES(dict[str, str]) –Display-name overrides for solver array names that title-casing alone leaves cryptic.
-
SCALARS_ARRAY–The point/cell array every reduction is written to, so one mapper name serves every field and mode.
Bounds
module-attribute
¶
A pyvista axis-aligned bounding box, as (xmin, xmax, ymin, ymax, zmin, zmax).
FLUX_DENSITY
module-attribute
¶
The MagnetoDynamicsCalcFields name for B in its nodal form; the elemental form the solver writes by default appends " e".
FIELD_RENAMES
module-attribute
¶
Display-name overrides for solver array names that title-casing alone leaves cryptic.
SCALARS_ARRAY
module-attribute
¶
The point/cell array every reduction is written to, so one mapper name serves every field and mode.
FieldLines
dataclass
¶
FieldLines(vtu_path: str | Path, options: FieldLineOptions | None = None)
A Renderable for the solved B-field streamlines of one case.vtu.
VTU read + streamline integration run in __post_init__ (whichever worker thread constructs it); render only draws precomputed actors, keeping the plotter thread free.
Methods:
-
render–Draw the precomputed field lines into
plotter.
Attributes:
-
vtu_path(str | Path) –The solved
case.vtuwhose B field the lines follow. -
options(FieldLineOptions | None) –The streamline options; None uses the defaults.
vtu_path
instance-attribute
¶
The solved case.vtu whose B field the lines follow.
options
class-attribute
instance-attribute
¶
options: FieldLineOptions | None = None
The streamline options; None uses the defaults.
render
¶
Draw the precomputed field lines into plotter.
Source code in src/femforge/viz/field_lines.py
FieldLineOptions
pydantic-model
¶
Bases: BaseModel
Typed options for the 3D field-line render.
Config:
use_attribute_docstrings:Truevalidate_assignment:True
Fields:
-
seed_placement(SeedPlacement) -
seed_grid(bool) -
line_count(int) -
max_length(float) -
colormap(Colormap | str | list[str]) -
invert(bool) -
log_scale(bool) -
clim(tuple[float, float] | None) -
opacity_map(tuple[float, float] | None) -
opacity(float | OpacityTransfer) -
interpolator(InterpolatorType) -
seed_fraction(float) -
region_array(str | None) -
region_id(int | None) -
clip_to_region(bool) -
tube_radius(float | None) -
initial_step_length(float) -
min_step_length(float) -
max_step_length(float) -
show_outline(bool) -
vectors(str | None)
seed_placement
pydantic-field
¶
seed_placement: SeedPlacement = SeedPlacement.VOLUME
Where to seed the streamlines within the domain bounding box.
seed_grid
pydantic-field
¶
seed_grid: bool = True
Seed the streamlines on a grid (True) or at random points (False).
line_count
pydantic-field
¶
line_count: int = 12
Seed points per axis: CENTER_PLANE seeds line_count², VOLUME line_count³, GAP_LINE line_count.
max_length
pydantic-field
¶
max_length: float = 0.75
[-]: Fraction of the domain diagonal a streamline may integrate along, keeping the picture framed on the magnets.
colormap
pydantic-field
¶
The |B| colormap: a Colormap member, any matplotlib or colorcet colormap name, or a list of colors interpolated across the scalar range.
clim
pydantic-field
¶
[?]: The |B| color limits, or None for the lines' own range.
opacity_map
pydantic-field
¶
[-]: The opacity at the low and high color limits, linear in the color mapping between them; it replaces an OpacityTransfer.
opacity
pydantic-field
¶
opacity: float | OpacityTransfer = 1.0
[-]: Line or tube opacity: a constant in [0, 1], or an OpacityTransfer that maps |B| to opacity like the color.
interpolator
pydantic-field
¶
interpolator: InterpolatorType = InterpolatorType.CELL
The integrator's cell-location strategy. CELL (default) fixes the straight "spike" streamlines a point locator produces near the air↔magnet interface.
seed_fraction
pydantic-field
¶
seed_fraction: float = 0.6
[-]: Fraction of the bounding box, centered, that the seed grid spans, keeping seeds out of the outer air shell where B ≈ 0.
region_array
pydantic-field
¶
region_array: str | None = None
Name of a cell-data region-id array (e.g. Elmer's "GeometryIds") identifying each cell's body. Used with region_id and clip_to_region.
region_id
pydantic-field
¶
region_id: int | None = None
The single region id to confine integration to when clip_to_region is set (e.g. the air body id).
clip_to_region
pydantic-field
¶
clip_to_region: bool = False
Confine streamline integration to region_id (needs region_array and region_id), which keeps elemental B from averaging across the air↔magnet interface.
tube_radius
pydantic-field
¶
tube_radius: float | None = None
r_tube [m]: Streamline tube radius; None draws the streamlines as plain poly-lines.
initial_step_length
pydantic-field
¶
initial_step_length: float = 0.5
[-]: The integrator's initial step, in cell lengths; smaller values follow tight curves.
min_step_length
pydantic-field
¶
min_step_length: float = 0.01
[-]: The integrator's smallest step, in cell lengths.
max_step_length
pydantic-field
¶
max_step_length: float = 1.0
[-]: The integrator's largest step, in cell lengths.
SeedPlacement
¶
Bases: StrEnum
Where the streamline seed points are placed within the domain bounding box.
Attributes:
-
CENTER_PLANE–A
line_count×line_countgrid on the mid-Z plane (the field-line cross-section). -
VOLUME–A
line_count³ grid filling the box — denser, fuller 3D coverage (the default). -
GAP_LINE–A single line of
line_countpoints along X through the center (e.g. across the Halbach gap).
CENTER_PLANE
class-attribute
instance-attribute
¶
A line_count × line_count grid on the mid-Z plane (the field-line cross-section).
VOLUME
class-attribute
instance-attribute
¶
A line_count³ grid filling the box — denser, fuller 3D coverage (the default).
GAP_LINE
class-attribute
instance-attribute
¶
A single line of line_count points along X through the center (e.g. across the Halbach gap).
Colormap
¶
Bases: StrEnum
Perceptually-uniform matplotlib colormaps for the |B| magnitude scale.
Attributes:
OpacityTransfer
¶
Bases: StrEnum
A pyvista opacity transfer function that maps the |B| scalar to per-element opacity; the _r variants reverse the ramp.
Attributes:
-
LINEAR–Opacity rises linearly with
|B|. -
LINEAR_R–Opacity falls linearly with
|B|. -
GEOM–Opacity rises geometrically with
|B|. -
GEOM_R–Opacity falls geometrically with
|B|. -
SIGMOID–Opacity follows a sigmoid in
|B|, so weak-field lines fade out. -
SIGMOID_R–Opacity follows a reversed sigmoid in
|B|, so strong-field lines fade out.
LINEAR_R
class-attribute
instance-attribute
¶
Opacity falls linearly with |B|.
SIGMOID
class-attribute
instance-attribute
¶
Opacity follows a sigmoid in |B|, so weak-field lines fade out.
SIGMOID_R
class-attribute
instance-attribute
¶
Opacity follows a reversed sigmoid in |B|, so strong-field lines fade out.
InterpolatorType
¶
Bases: StrEnum
The cell-location strategy the streamline integrator uses (pyvista's interpolator_type).
Both integrate the same point vector field; this only changes how each step finds its containing cell.
Attributes:
-
CELL–Locate cells with a cell locator, the right default for this geometry.
-
POINT–Locate cells via the nearest mesh point (pyvista's default). Faster, but near interfaces/thin features it can grab the wrong
CELL
class-attribute
instance-attribute
¶
Locate cells with a cell locator, the right default for this geometry.
It stays robust near the air↔magnet interface and thin air gaps, where a point locator mislocates a step into the wrong (magnet) cell and sends the streamline off as a straight "spike".
POINT
class-attribute
instance-attribute
¶
Locate cells via the nearest mesh point (pyvista's default). Faster, but near interfaces/thin features it can grab the wrong cell's vector and produce the spike streamlines.
StreamlineActor
¶
Bases: StrEnum
The plotter actor names draw_streamlines registers, so toggling the overlay off is a single remove_actor.
Attributes:
StreamlineActors
dataclass
¶
StreamlineActors(streamlines: PolyData, b_name: str, outline: PolyData | None, magnitudes: list[NDArray[float64]])
The precomputed drawables for a field-line view, split from plotting so the expensive part runs off the UI thread.
Built by build_streamlines (worker-thread safe) and drawn by draw_streamlines (plotter thread only).
Attributes:
-
streamlines(PolyData) –The integrated streamlines, clipped to the integration region.
-
b_name(str) –The name of the B array the lines carry for coloring.
-
outline(PolyData | None) –The domain's bounding-box outline; None when
show_outlineis off. -
magnitudes(list[NDArray[float64]]) –The integrated field's magnitudes over the integration region, one chunk per body, which set the lines' color range.
Association
¶
Bases: StrEnum
Whether a VTU array lives on mesh points or cells (pyvista's preference).
Attributes:
-
POINT–One value per mesh point.
-
CELL–One value per mesh cell.
-
intensitymode(str) –The plotly
Mesh3d.intensitymodename for this association.
BodyPaint
¶
Bases: StrEnum
Where a body's color comes from.
Attributes:
BodyStyle
pydantic-model
¶
Bases: BaseModel
A body's own look: where its color comes from, a solid color when it has one, and its opacity.
Config:
use_attribute_docstrings:Truefrozen:True
Fields:
Validators:
-
_solid_has_color
DisplayMode
¶
Bases: StrEnum
How a field array is reduced to the value that drives the color.
Attributes:
-
VALUE–The value itself.
-
ABSVALUE–The absolute value.
-
X–The x component.
-
Y–The y component.
-
Z–The z component.
-
MAGNITUDE–The vector magnitude.
-
POLAR_XY–The in-plane direction as hue, brightened by the in-plane magnitude.
-
label(str) –The mode's name as it reads in a picker.
POLAR_XY
class-attribute
instance-attribute
¶
The in-plane direction as hue, brightened by the in-plane magnitude.
DisplaySpec
pydantic-model
¶
Bases: BaseModel
The complete, serializable state of one field display: which array is colored, how it reduces, and how the colors map.
Config:
use_attribute_docstrings:Truevalidate_assignment:True
Fields:
-
field(str) -
mode(DisplayMode) -
colormap(str) -
log_scale(bool) -
invert(bool) -
clim(tuple[float, float] | None) -
robust(bool) -
hidden_bodies(tuple[str, ...]) -
outline(bool) -
opacity(float) -
opacity_map(tuple[float, float] | None) -
body_styles(tuple[BodyStyle, ...]) -
body_colormap(str) -
streamlines(FieldLineOptions | None)
field
pydantic-field
¶
field: str = ''
Name of the VTU array to color by; empty means "whichever the run offers first".
mode
pydantic-field
¶
mode: DisplayMode = DisplayMode.VALUE
How the array is reduced to the displayed value.
colormap
pydantic-field
¶
colormap: str = 'viridis'
Colormap name, resolved through pyvista's get_cmap_safe (matplotlib and colorcet names both work).
log_scale
pydantic-field
¶
log_scale: bool = False
Map the color range logarithmically; only the strictly positive values take part.
clim
pydantic-field
¶
[?]: Pinned color limits in the displayed value's unit, or None to recompute them from the data on every apply.
robust
pydantic-field
¶
robust: bool = True
Clamp the automatic limits to the 2-98 percentiles so a few outlier cells cannot flatten the picture.
hidden_bodies
pydantic-field
¶
Body names to hide, by their entities.json name.
outline
pydantic-field
¶
outline: bool = True
Draw the black feature-edge wireframe over the visible bodies.
opacity_map
pydantic-field
¶
[-]: The opacity at the low and high color limits, linear in the color mapping between them; None draws opacity throughout.
body_styles
pydantic-field
¶
Bodies with a color source or an opacity of their own; the rest take the field colormap at full opacity.
body_colormap
pydantic-field
¶
body_colormap: str = 'batlow'
The colormap the COLORMAP bodies share, in body_styles order.
streamlines
pydantic-field
¶
streamlines: FieldLineOptions | None = None
Options for the field-line overlay, or None to draw none.
solid
¶
The color of every body not on the field colormap, by body: its own, or its share of the body colormap.
Source code in src/femforge/viz/field_display.py
body_opacity
¶
A body's drawn opacity: its own times the overall one.
unmatched
¶
The hidden_bodies and body_styles names missing from bodies, in spec order.
Source code in src/femforge/viz/field_display.py
fitted
¶
fitted(fields: Sequence[FieldInfo]) -> DisplaySpec
This spec snapped to what a run actually offers: an unset field takes the first available one and a mode the field disallows falls back to its first allowed mode.
An unknown field name raises KeyError naming the available arrays.
Source code in src/femforge/viz/field_display.py
FieldInfo
dataclass
¶
FieldInfo(name: str, association: Association, components: int, dtype: str)
One displayable VTU array: where it lives, how wide it is, and which display modes it supports.
Attributes:
-
name(str) –The array's name in the VTU.
-
association(Association) –Whether the array lives on points or cells.
-
components(int) –The number of components per value: 1 for a scalar, 3 for a vector.
-
dtype(str) –The array's numpy dtype name.
-
display_name(str) –The array's name as it reads in a picker, with the
FIELD_RENAMESoverrides applied. -
modes(tuple[DisplayMode, ...]) –The display modes this array supports, the default first: the vector set for a 3-component field, the scalar pair otherwise.
association
instance-attribute
¶
association: Association
Whether the array lives on points or cells.
components
instance-attribute
¶
components: int
The number of components per value: 1 for a scalar, 3 for a vector.
display_name
property
¶
display_name: str
The array's name as it reads in a picker, with the FIELD_RENAMES overrides applied.
modes
property
¶
modes: tuple[DisplayMode, ...]
The display modes this array supports, the default first: the vector set for a 3-component field, the scalar pair otherwise.
FieldScene
¶
FieldScene(*, grid: UnstructuredGrid, blocks: MultiBlock, fields: Sequence[FieldInfo], model_dim: int, run_id: str, bodies: Bodies | None = None)
One run's solved bodies as a recolorable field display.
It is a Renderable for the pyvista path and the trace source for the 2D plotly path; both read the same DisplaySpec.
Parameters:
-
grid(UnstructuredGrid) –The solved VTU grid.
-
blocks(MultiBlock) –The grid split into one block per named body.
-
fields(Sequence[FieldInfo]) –The displayable arrays.
-
model_dim(int) –2 for an axisymmetric slice, else 3.
-
run_id(str) –The run bundle's name.
-
bodies(Bodies | None, default:None) –The named bodies from
entities.json; None names none.
Methods:
-
from_run–Open a run bundle's VTU as a field scene, its bodies split and named from
entities.json. -
field_info–The
FieldInfofor an array name, resolved the same way a field query resolves one. -
apply–Write the spec's reduction into every block's
display_scalarsarray and return the color limits it produced. -
render–Draw the whole display into
plotter: the composite body actor, then everythingupdateowns; solid bodies an earlier scene left go first. -
update–Recolor an already-rendered scene in place — the cheap path a panel calls on every knob change; field lines are re-integrated only when their options changed.
-
shown_blocks–The blocks of every body not in
hidden, under their names. -
integrated–The cached field lines when
optionsonly restyle them, None when they need integrating. -
integrate_streamlines–Seed and integrate the field lines through this scene's grid — the compute half, safe off the UI thread.
-
region_magnitudes–The magnitudes of array
nameper body of a region (every body for None), the chunks a field-line range spans. -
show_streamlines–Draw integrated field lines into
plotterin the display's mapping, record their options as the drawn ones and keep the lines for a restyle. -
lines_pinned–Whether field lines following
vectorstake the display's pinned range: it is pinned and shows that field's magnitude. -
lines_title–The field lines' scalar bar title: the integrated field's name.
-
line_style–The field lines in the display's colormap, inversion, log scale and opacity map; a polar display leaves them as asked.
-
figure–The plotly figure dict for the 2D path: one
Mesh3dper body (hidden oneslegendonly) plus the outline, under an orthographic top-down camera.
Attributes:
-
drawn_lines(FieldLineOptions | None) –The styled options of the lines the plotter holds.
Source code in src/femforge/viz/field_display.py
drawn_lines
instance-attribute
¶
drawn_lines: FieldLineOptions | None = None
The styled options of the lines the plotter holds.
from_run
classmethod
¶
from_run(run: Run) -> FieldScene
Open a run bundle's VTU as a field scene, its bodies split and named from entities.json.
Source code in src/femforge/viz/field_display.py
field_info
¶
The FieldInfo for an array name, resolved the same way a field query resolves one.
Source code in src/femforge/viz/field_display.py
apply
¶
apply(spec: DisplaySpec) -> tuple[float, float]
Write the spec's reduction into every block's display_scalars array and return the color limits it produced.
Source code in src/femforge/viz/field_display.py
render
¶
Draw the whole display into plotter: the composite body actor, then everything update owns; solid bodies an earlier scene left go first.
Source code in src/femforge/viz/field_display.py
update
¶
update(plotter: Plotter, spec: DisplaySpec) -> None
Recolor an already-rendered scene in place — the cheap path a panel calls on every knob change; field lines are re-integrated only when their options changed.
Source code in src/femforge/viz/field_display.py
shown_blocks
¶
The blocks of every body not in hidden, under their names.
Source code in src/femforge/viz/field_display.py
integrated
¶
integrated(options: FieldLineOptions) -> StreamlineActors | None
The cached field lines when options only restyle them, None when they need integrating.
Source code in src/femforge/viz/field_display.py
integrate_streamlines
¶
integrate_streamlines(options: FieldLineOptions) -> StreamlineActors
Seed and integrate the field lines through this scene's grid — the compute half, safe off the UI thread.
Source code in src/femforge/viz/field_display.py
region_magnitudes
¶
The magnitudes of array name per body of a region (every body for None), the chunks a field-line range spans.
Source code in src/femforge/viz/field_display.py
show_streamlines
¶
show_streamlines(plotter: Plotter, actors: StreamlineActors, options: FieldLineOptions) -> None
Draw integrated field lines into plotter in the display's mapping, record their options as the drawn ones and keep the lines for a restyle.
Parameters:
-
plotter(Plotter) –The plotter to draw into.
-
actors(StreamlineActors) –The integrated field lines.
-
options(FieldLineOptions) –The options the lines were integrated with.
Source code in src/femforge/viz/field_display.py
lines_pinned
¶
Whether field lines following vectors take the display's pinned range: it is pinned and shows that field's magnitude.
Source code in src/femforge/viz/field_display.py
lines_title
¶
line_style
¶
line_style(options: FieldLineOptions, actors: StreamlineActors) -> FieldLineOptions
The field lines in the display's colormap, inversion, log scale and opacity map; a polar display leaves them as asked.
Their range is the display's pinned one while it shows their field's magnitude, else the automatic range of that magnitude over their own region, whatever the bodies show.
Source code in src/femforge/viz/field_display.py
figure
¶
figure(spec: DisplaySpec) -> dict[str, object]
The plotly figure dict for the 2D path: one Mesh3d per body (hidden ones legendonly) plus the outline, under an orthographic top-down camera.
POLAR_XY falls back to the magnitude, a log scale plots log10 with decade ticks, and opacity_map draws as opacity.
Source code in src/femforge/viz/field_display.py
SceneActor
¶
Bases: StrEnum
The plotter actor names a FieldScene registers, so a toggle removes exactly one.
Methods:
-
of–The actor name of one body under this prefix.
Attributes:
Renderable
¶
Scene
¶
Scene(*items: Renderable)
An ordered group of Renderables drawn into one plotter refresh: clear once, draw in order (later items on top), repaint once.
Scene is itself a Renderable, so scenes can nest.
Methods:
-
add–Append a renderable to draw; returns
selfso calls chain. -
render–Clear the plotter, draw every item in order, and repaint — once. Call on the plotter thread.
Source code in src/femforge/viz/scene.py
add
¶
add(item: Renderable) -> Scene
render
¶
Clear the plotter, draw every item in order, and repaint — once. Call on the plotter thread.
select_flux_density_array
¶
Pick the B array from a VTU's array names: the nodal form first (no cell→point projection needed), then the elemental "... e", then any name containing the phrase (case-insensitive).
Raises KeyError naming the available arrays if none matches.
Source code in src/femforge/viz/field_lines.py
seed_points
¶
seed_points(bounds: Bounds, options: FieldLineOptions) -> list[Point3]
The (N, 3) streamline seed coordinates for the domain bounds and options (pure Python — unit-testable without a render context).
The grid is centered and spans seed_fraction of each axis, keeping seeds out of the outer air shell where B ≈ 0.
Source code in src/femforge/viz/field_lines.py
build_streamlines
¶
build_streamlines(dataset: DataSet, b_name: str, options: FieldLineOptions | None = None) -> StreamlineActors
Seed and integrate |B| streamlines through a dataset that already carries B as point data, without touching a plotter.
Parameters:
-
dataset(DataSet) –The dataset carrying B on its points.
-
b_name(str) –The point array the lines follow.
-
options(FieldLineOptions | None, default:None) –The field-line options; None takes the defaults.
Source code in src/femforge/viz/field_lines.py
build_streamlines_from_vtu
¶
build_streamlines_from_vtu(vtu_path: str | Path, options: FieldLineOptions | None = None) -> StreamlineActors
Read a solved case.vtu and integrate its B-field streamlines into a drawable StreamlineActors — no plotter touched, safe off the UI thread.
Source code in src/femforge/viz/field_lines.py
prepare_streamline_source
¶
prepare_streamline_source(grid: UnstructuredGrid, options: FieldLineOptions) -> tuple[DataSet, str]
Narrow a read grid to the integration region and put B on its points, returning the dataset and the B array name — the read-independent half of build_streamlines_from_vtu.
Source code in src/femforge/viz/field_lines.py
draw_streamlines
¶
draw_streamlines(actors: StreamlineActors, options: FieldLineOptions, plotter: Plotter) -> None
Draw a precomputed StreamlineActors into plotter without clearing or showing it, so it composes inside a Scene.
Parameters:
-
actors(StreamlineActors) –The integrated lines; an empty set removes any lines drawn before.
-
options(FieldLineOptions) –The field-line options that style them.
-
plotter(Plotter) –The plotter to draw into, on its own thread.
Source code in src/femforge/viz/field_lines.py
render_streamlines
¶
render_streamlines(dataset: DataSet, b_name: str, options: FieldLineOptions | None = None, *, off_screen: bool = False, screenshot: str | Path | None = None, plotter: Plotter | None = None) -> None
One-shot: build streamlines through dataset and draw them, in a plotter of its own when plotter is None.
Parameters:
-
dataset(DataSet) –The dataset carrying B on its points.
-
b_name(str) –The point array the lines follow.
-
options(FieldLineOptions | None, default:None) –The field-line options; None takes the defaults.
-
off_screen(bool, default:False) –Render without a window.
-
screenshot(str | Path | None, default:None) –The PNG to write when rendering off screen.
-
plotter(Plotter | None, default:None) –A live plotter to add the lines to instead of opening one.
Source code in src/femforge/viz/field_lines.py
render_field_lines
¶
render_field_lines(vtu_path: str | Path, options: FieldLineOptions | None = None, *, off_screen: bool = False, screenshot: str | Path | None = None, plotter: Plotter | None = None) -> None
Render the magnetic flux-density field lines from a solved case.vtu, headless to a PNG or in an interactive window.
Parameters:
-
vtu_path(str | Path) –The solved
case.vtu. -
options(FieldLineOptions | None, default:None) –The field-line options; None takes the defaults.
-
off_screen(bool, default:False) –Render without a window.
-
screenshot(str | Path | None, default:None) –The PNG to write when rendering off screen.
-
plotter(Plotter | None, default:None) –A live plotter to add the lines to instead of opening one.
Source code in src/femforge/viz/field_lines.py
field_infos
¶
field_infos(point_arrays: Mapping[str, AnyArray], cell_arrays: Mapping[str, AnyArray]) -> list[FieldInfo]
Every displayable array of a VTU as a FieldInfo, GeometryIds excluded, sorted by display name.
Source code in src/femforge/viz/field_display.py
reduce_field
¶
reduce_field(values: AnyArray, mode: DisplayMode) -> FloatArray
The scalar a display mode draws from one field array.
VALUE passes the array through and POLAR_XY returns the XY magnitude (the quantity that sets the color range; the angle rides along as hue).
Source code in src/femforge/viz/field_display.py
polar_angle
¶
Each vector's XY direction as a cyclic coordinate in [0, 1] — atan2(y, x) mapped off [-pi, pi].
Source code in src/femforge/viz/field_display.py
polar_rgba
¶
Per-vector RGBA for DisplayMode.POLAR_XY: hue from the XY angle through a cyclic cmap, brightness and alpha from the sigmoid-scaled XY magnitude.
Parameters:
-
values(AnyArray) –The
(N, 3)vectors. -
lo(float) –The XY magnitude at the dark end.
-
hi(float) –The XY magnitude at the bright end.
-
cmap(Colormapper) –The cyclic colormap the XY angle maps through.
Source code in src/femforge/viz/field_display.py
color_range
¶
color_range(chunks: Iterable[AnyArray], *, log_scale: bool = False, robust: bool = True) -> tuple[float, float]
The (lo, hi) color limits spanning every scalar chunk's own range, from the finite values only; an empty selection gives (0.0, 1.0).
Parameters:
-
chunks(Iterable[AnyArray]) –The scalar arrays, one per body.
-
log_scale(bool, default:False) –Keep only the strictly positive values and start at their 1st percentile.
-
robust(bool, default:True) –Clamp each chunk to its 2-98 percentiles, so a small body keeps its range beside a large one.
Source code in src/femforge/viz/field_display.py
camera_needs_reset
¶
camera_needs_reset(position: Sequence[float], focal: Sequence[float], bounds: Sequence[float] | None, *, half_angle_deg: float = 30.0) -> bool
Whether the camera has lost the model, with the box behind it or outside its view cone; a camera inside the box always keeps its view.
Parameters:
-
position(Sequence[float]) –The camera position.
-
focal(Sequence[float]) –The camera's focal point.
-
bounds(Sequence[float] | None) –The model box as
(xmin, xmax, ymin, ymax, zmin, zmax); missing or non-finite bounds always re-frame. -
half_angle_deg(float, default:30.0) –The half angle of the view cone some box corner must fall inside, in degrees.
Source code in src/femforge/viz/field_display.py
plotly_colorscale
¶
plotly_colorscale(samples: AnyArray, *, invert: bool = False) -> Colorscale
A plotly colorscale from sampled RGB(A) rows: evenly-spaced stops paired with "rgb(r,g,b)" strings.
Source code in src/femforge/viz/field_display.py
log_colorbar_ticks
¶
Decade tick positions spanning a log color range, with their 1e-notation labels.
Source code in src/femforge/viz/field_display.py
mesh3d_traces
¶
mesh3d_traces(points: FloatArray, triangles: IntArray, intensity: FloatArray | None, *, name: str, color: str | None = None, opacity: float = 1.0, intensitymode: Association = POINT, colorscale: Colorscale | None = None, cmin: float | None = None, cmax: float | None = None, showscale: bool = False, hovertemplate: str | None = None, customdata: FloatArray | None = None, colorbar: TraceDict | None = None, visible: bool = True) -> list[TraceDict]
One plotly Mesh3d trace as a plain JSON dict: a body's triangulated surface colored by intensity, or by color alone.
Parameters:
-
points(FloatArray) –The
(N, 3)vertex coordinates. -
triangles(IntArray) –The
(M, 3)vertex indices of each triangle. -
intensity(FloatArray | None) –The values the colorscale maps, per vertex or per triangle; None colors by
coloralone. -
name(str) –The legend name.
-
color(str | None, default:None) –A solid color for a body without an intensity.
-
opacity(float, default:1.0) –The trace opacity.
-
intensitymode(Association, default:POINT) –Whether
intensitylives on the vertices or the triangles. -
colorscale(Colorscale | None, default:None) –The plotly colorscale
intensitymaps through. -
cmin(float | None, default:None) –The intensity at the low end of the colorscale.
-
cmax(float | None, default:None) –The intensity at the high end of the colorscale.
-
showscale(bool, default:False) –Draw the colorbar.
-
hovertemplate(str | None, default:None) –The plotly hover text template.
-
customdata(FloatArray | None, default:None) –Per-vertex values the hover template reads.
-
colorbar(TraceDict | None, default:None) –The plotly colorbar settings.
-
visible(bool, default:True) –Draw the body; a hidden one stays in the legend as
legendonly.
Source code in src/femforge/viz/field_display.py
outline_traces
¶
outline_traces(segments: FloatArray, *, name: str = 'outline', color: str = 'black') -> list[TraceDict]
One plotly Scatter3d lines trace drawing every (N, 2, 3) segment, NaN-separated so the segments stay disjoint.
Parameters:
-
segments(FloatArray) –The
(N, 2, 3)line segments. -
name(str, default:'outline') –The trace name.
-
color(str, default:'black') –The line color.
Source code in src/femforge/viz/field_display.py
list_fields
¶
Every displayable field of a VTU grid (GeometryIds excluded), sorted by display name.
Source code in src/femforge/viz/field_display.py
split_by_body
¶
split_by_body(grid: UnstructuredGrid, bodies: Bodies) -> MultiBlock
The grid split into one block per named body, keyed by its entities.json name via the GeometryIds cell array.
Source code in src/femforge/viz/field_display.py
feature_outline
¶
The feature and boundary edges of a multiblock's outer surface — the black wireframe drawn over the field, the body outlines on a 2D slice — or None when the surface has none.
Source code in src/femforge/viz/field_display.py
model_dim_of
¶
model_dim_of(grid: DataSet) -> int
2 for a flat (axisymmetric slice) grid with no Z extent, else 3.
Source code in src/femforge/viz/field_display.py
sample_colormap
¶
count evenly-spaced RGBA rows from a named colormap, resolved through pyvista's get_cmap_safe.
Source code in src/femforge/viz/field_display.py
surface_triangles
¶
surface_triangles(block: DataSet) -> tuple[FloatArray, IntArray]
A block's outer surface as (points, triangles): an (N, 3) coordinate array and an (M, 3) vertex-index array.
Source code in src/femforge/viz/field_display.py
outline_segments
¶
The feature edges as an (N, 2, 3) array of line segments.