Results¶
Post-processing container.
Fluent selection — .nodes.select() / .elements.select()¶
results.nodes.select(...) and results.elements.select(...) are the
results entries of the unified, daisy-chainable
selection idiom. .select() returns a
MeshSelection (point
family); the terminal is .values(component=...), which forwards to
the retained results.<level>.get(...) reader and returns the
same slab (NodeSlab / ElementSlab) with id/value parity.
slab = (results.nodes.select(pg="Base")
.in_box(lo, hi) # half-open [lo, hi)
.on_plane((0, 0, 0), (0, 0, 1), tol=1e-6)
.values(component="displacement_x")) # -> NodeSlab
A bare results selection needs a component — .result() raises
RuntimeError; use .values(component=...). Element spatial verbs
operate on element centroids.
S5 — formerly-silent results paths now raise
results with selection= on an import-origin
(from_msh/MPCO/native) FEMData now raises RuntimeError
instead of resolving to an empty set; results element-centroid
computation raises KeyError on an unknown connectivity node,
which also makes the legacy
results.elements.in_box/nearest_to/on_plane helpers fail
loud. See the changelog.
See Selection for the full idiom; results
sub-composite .select() (gauss/fibers/layers/line_stations/
springs) is a tracked, not-yet-shipped follow-up.
apeGmsh.results.Results.Results ¶
Results(reader: ResultsReader, *, fem: 'Optional[FEMData]' = None, stage_id: Optional[str] = None, path: Optional[Path] = None)
Top-level results object. Returned by Results.from_* constructors.
Stage scoping¶
Instances may be unscoped (top-level — accesses any stage) or
scoped to one stage (returned by .stage(name),
.modes[i]). Scoped instances expose stage metadata as
properties (.kind, .time, .n_steps); mode-scoped
instances additionally expose .eigenvalue, .frequency_hz,
.period_s, .mode_index.
Source code in src/apeGmsh/results/Results.py
modes
property
¶
Stages with kind='mode' as a list of mode-scoped Results.
Order is the order the modes were written (typically by
ascending mode_index). For a stable lookup by index, sort:
sorted(results.modes, key=lambda m: m.mode_index).
plot
property
¶
results.plot — static matplotlib renderer.
Mirrors the interactive viewer's diagram catalog as headless, publication-ready matplotlib figures::
results.plot.contour("displacement_z", step=-1)
results.plot.deformed(step=-1, scale=50, component="stress_xx")
results.plot.history(node=412, component="displacement_x")
Requires the [plot] extra (matplotlib).
from_native
classmethod
¶
Open an apeGmsh native HDF5 results file.
If fem is omitted, the embedded /model/ snapshot is
used as the bound FEMData. If fem is provided and the file
embeds a snapshot, the two snapshot_id hashes must match.
Source code in src/apeGmsh/results/Results.py
from_recorders
classmethod
¶
from_recorders(spec, output_dir: str | Path, *, fem: 'FEMData', cache_root: str | Path | None = None, stage_name: str = 'analysis', stage_kind: str = 'transient', file_format: str = 'out', stage_id: str | None = None) -> 'Results'
Open the result of an OpenSees run driven by Tcl/Py recorders.
Parses the .out / .xml files emitted at
output_dir (matching what spec.emit_recorders(...) or
the apeGmsh OpenSees bridge's Tcl/Py emit produced) into an
apeGmsh native HDF5, caches the result at
cache_root, and opens it through NativeReader.
Caching: subsequent calls with unchanged input files return
the cached HDF5 directly (file mtime + size + spec
snapshot_id form the cache key). See
writers/_cache.py.
stage_id matches the per-stage filename prefix used by
:meth:ResolvedRecorderSpec.emit_recorders together with
begin_stage(stage_id, ...). When set, only files prefixed
with <stage_id>__ are read; stage_name defaults to
stage_id if not overridden. None (default) keeps the
legacy flat-naming used by Tcl/Py exports.
Phase 6 v1 supports nodal records only; element-level records in the spec are skipped with a note. The capture flow (Phase 7) handles modal recorders.
Source code in src/apeGmsh/results/Results.py
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 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 | |
from_mpco
classmethod
¶
from_mpco(path: 'str | Path | list[str | Path]', *, fem: 'Optional[FEMData]' = None, merge_partitions: bool = True) -> 'Results'
Open a STKO .mpco HDF5 results file.
Single-file mode (default for non-partitioned analyses): pass
the path of one .mpco file. Synthesizes a partial FEMData
from the MPCO MODEL/ group if fem is omitted.
Multi-partition mode (parallel OpenSees runs): pass either
- a single
<stem>.part-<N>.mpcopath — siblings are discovered automatically by globbing<stem>.part-*.mpcoin the same directory and merged into one virtual reader; - an explicit list of partition paths.
Boundary nodes deduplicate by ID (first-occurrence wins); elements concatenate (disjoint by partition); slabs stitch across partitions transparently. Stage and time vectors must match across partitions or construction raises.
Pass merge_partitions=False to opt out of auto-discovery
and read only the file at path even if it follows the
.part-N naming convention.
Source code in src/apeGmsh/results/Results.py
bind ¶
Re-bind to fem.
Useful when you've re-built the same mesh in a fresh session and want labels / Parts that the embedded snapshot doesn't carry. No hash validation is performed — pairing the FEMData with a results file from the same run is the user's responsibility.
Source code in src/apeGmsh/results/Results.py
stage ¶
Return a Results scoped to a stage (matched by id or name).
close ¶
viewer ¶
viewer(*, blocking: bool = True, title: Optional[str] = None, restore_session: 'bool | str' = 'prompt', save_session: bool = True, cuts: 'Optional[Any]' = None, model_h5: 'Optional[Any]' = None)
Open the post-solve results viewer.
Parameters¶
blocking
True (default) — open the viewer in-process and block
the calling thread until the window closes. Matches the
signature of :meth:g.mesh.viewer and :meth:g.model.viewer.
False — spawn a subprocess via
python -m apeGmsh.viewers <path> so the notebook /
kernel can keep running. Requires that the Results was
opened from disk (self._path is set); raises
:class:RuntimeError for in-memory Results.
title
Optional window title; defaults to "Results — <filename>".
restore_session
How to handle a previously-saved session JSON next to the
results file. True restores silently, False ignores,
"prompt" (default) opens a yes/no dialog if a matching
session exists. No effect for in-memory Results.
save_session
If True (default), the active set of diagrams + scrubber
position is saved to <results>.viewer-session.json when
the window closes. False disables auto-save.
cuts
Optional sequence of :class:apeGmsh.cuts.SectionCutDef
instances to render as Layers at boot. Each cut becomes a
new SectionCutDiagram in the active geometry's
"Section cuts" composition (created if absent). Requires
model_h5 so OpenSees tags can be mapped back to FEM
eids — pass it alongside cuts. Subprocess launches
(blocking=False) currently ignore this argument; build
cuts programmatically via director.add_section_cut on
the spawned viewer once it exposes IPC.
model_h5
Path to a model.h5 that carries OpenSees enrichment:
/opensees/cuts (for section-cut tag mapping) and / or
/opensees/transforms + /opensees/element_meta (for
per-element beam orientation, ADR 0018). When omitted and
self was opened from disk via :meth:from_native, the
viewer auto-resolves the results file itself as the
orientation source if it carries those zones; cuts
auto-load still requires an explicit model_h5=.
Forwarded into the subprocess on blocking=False via
--model-h5 so the auto-resolve also fires there for
non-default layouts.
Returns¶
ResultsViewer
The viewer instance after the window closes (blocking).
subprocess.Popen
The spawned process handle (non-blocking).
None
If APEGMSH_SKIP_VIEWER is set in the environment. This
lets the same cell run under jupyter nbconvert --execute
or in CI without spawning a GUI window.
Source code in src/apeGmsh/results/Results.py
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | |
Slabs¶
Tabular dataclasses returned by reader queries.
apeGmsh.results._slabs ¶
Slab dataclasses returned by ResultsReader implementations.
A slab carries one component's values plus enough location metadata
that the caller can interpret each row without re-deriving it. They
are numpy-native and immutable; the viewer wraps them in xarray
when it wants labeled axes.
Shape conventions (single-stage, post-stitching across partitions):
================ ======================== =================================================
Slab values shape Location index fields
================ ======================== =================================================
NodeSlab (T, N) node_ids: (N,)
ElementSlab (T, E, npe) element_ids: (E,)
LineStationSlab (T, sum_S) element_index, station_natural_coord: (sum_S,)
GaussSlab (T, sum_GP) element_index: (sum_GP,),
natural_coords: (sum_GP, dim)
FiberSlab (T, sum_F) element_index, gp_index, y, z, area,
material_tag: (sum_F,)
LayerSlab (T, sum_L) element_index, gp_index, layer_index,
sub_gp_index, thickness: (sum_L,)
================ ======================== =================================================
For a single time step (time_slice was a scalar), T is 1 and
the leading axis is preserved — the caller can squeeze if desired.
NodeSlab
dataclass
¶
Node-level result values.
ElementSlab
dataclass
¶
Per-element-node values (e.g. globalForce / localForce).
LineStationSlab
dataclass
¶
LineStationSlab(component: str, values: ndarray, element_index: ndarray, station_natural_coord: ndarray, time: ndarray)
Beam line-diagram values per integration station.
GaussSlab
dataclass
¶
GaussSlab(component: str, values: ndarray, element_index: ndarray, natural_coords: ndarray, local_axes_quaternion: Optional[ndarray], time: ndarray)
Continuum Gauss-point values.
natural_coords are in parent space [-1, +1]. To get
global coordinates, call slab.global_coords(fem) — interpolates
through the bound FEMData's element shape functions for hex8 /
quad4, falling back to a centroid + bbox-scaled approximation for
element types that don't yet have explicit shape-fn support.
global_coords ¶
Map per-GP natural coords to (sum_GP, 3) world coords.
Uses element shape functions for supported types (hex8, quad4);
falls back to centroid + 0.5 * bbox_span * natural for
others — visualization-faithful for axis-aligned elements.
Source code in src/apeGmsh/results/_slabs.py
FiberSlab
dataclass
¶
FiberSlab(component: str, values: ndarray, element_index: ndarray, gp_index: ndarray, y: ndarray, z: ndarray, area: ndarray, material_tag: ndarray, time: ndarray)
Fiber-level values within fiber-section GPs.
LayerSlab
dataclass
¶
LayerSlab(component: str, values: ndarray, element_index: ndarray, gp_index: ndarray, layer_index: ndarray, sub_gp_index: ndarray, thickness: ndarray, local_axes_quaternion: ndarray, time: ndarray)
Layered shell layer values (one row per (elem, surf_gp, layer, sub_gp)).
SpringSlab
dataclass
¶
Zero-length spring values (one column per element, one spring index).
component encodes which spring is represented (e.g.
"spring_force_0" for the force in the first configured spring
direction). Each column in values corresponds to one element;
element_index carries the raw OpenSees element tag so the
caller can correlate columns with elements without needing a
separate ID array.
================ ========================
values (T, E)
element_index (E,)
================ ========================
Readers¶
Reader protocol and supporting types shared by every backend.
apeGmsh.results.readers._protocol ¶
Reader protocol — backend-agnostic contract for the composite layer.
Two implementations:
NativeReaderreads apeGmsh native HDF5 (Phase 1).MPCOReaderreads STKO MPCO HDF5 (Phase 3).
The composite layer above (Results.nodes.get(...) etc.) talks
only to this protocol — it never branches on backend type.
ResultLevel ¶
Bases: Enum
The topology level a component lives at.
StageInfo
dataclass
¶
StageInfo(id: str, name: str, kind: str, n_steps: int, eigenvalue: Optional[float] = None, frequency_hz: Optional[float] = None, period_s: Optional[float] = None, mode_index: Optional[int] = None)
Stage metadata returned by ResultsReader.stages().
For kind="mode", the eigenvalue/frequency/period/index
fields are populated and n_steps is 1. For other kinds,
the mode-only fields are None.
ResultsReader ¶
Bases: Protocol
Backend-agnostic reader protocol.
Implementations must support all six topology levels even if a
given file has no data at some of them; they should return empty
component lists from available_components() in that case
rather than raising.
stages ¶
time_vector ¶
partitions ¶
fem ¶
Embedded / synthesized FEMData snapshot.
NativeReader: reconstructs from/model/(always available).MPCOReader: synthesizes a partial FEMData from/MODEL/(no apeGmsh labels, no Part provenance).
Source code in src/apeGmsh/results/readers/_protocol.py
available_components ¶
Live capture¶
Recorder wiring used during a live OpenSees analysis.
LiveRecorders¶
apeGmsh.results.live._recorders.LiveRecorders ¶
LiveRecorders(spec: 'ResolvedRecorderSpec', output_dir: 'str | Path', *, file_format: str = 'out', ops=None)
Context manager that owns stage-scoped OpenSees recorders.
Parameters¶
spec
The :class:ResolvedRecorderSpec whose records to emit.
output_dir
Directory the recorder .out / .xml files land in.
Created on __enter__ if missing.
file_format
"out" (text) or "xml". Defaults to "out".
ops
The openseespy module (or a stand-in for testing). Defaults
to openseespy.opensees resolved lazily on __enter__.
Raises¶
RuntimeError
On __enter__ if the spec contains any modal records.
Source code in src/apeGmsh/results/live/_recorders.py
begin_stage ¶
Issue recorders for a new stage. Files are prefixed <name>__.
kind is forwarded to Results.from_recorders(...,
stage_kind=kind) when the stage is read back; valid values
are "transient" or "static".
Source code in src/apeGmsh/results/live/_recorders.py
end_stage ¶
Remove the current stage's recorders and flush their files.
Source code in src/apeGmsh/results/live/_recorders.py
LiveMPCO¶
apeGmsh.results.live._mpco.LiveMPCO ¶
Context manager that owns a single in-process MPCO recorder.
Parameters¶
spec
The :class:ResolvedRecorderSpec whose records to emit.
path
Output .mpco HDF5 file path. Parent directory created on
__enter__ if missing.
ops
The openseespy module (or a stand-in for testing). Defaults
to openseespy.opensees resolved lazily on __enter__.
Raises¶
RuntimeError
On __enter__ if ops.recorder('mpco', ...) fails — most
commonly because the openseespy build does not include the
MPCO recorder.
Source code in src/apeGmsh/results/live/_mpco.py
DomainCapture¶
apeGmsh.results.capture._domain.DomainCapture ¶
DomainCapture(spec: 'ResolvedDomainCaptureSpec', path: str | Path, fem: 'FEMData', *, ops: Any = None)
Context manager for in-process result capture.
Constructed live via ops.domain_capture(spec, path=...)
(bridge-attached) or off-line via :meth:DomainCapture.from_h5
(ndm / ndf sourced from a model.h5 /meta). The user
drives the analysis loop and calls step(t) to capture a
snapshot.
Source code in src/apeGmsh/results/capture/_domain.py
close ¶
Finalise any open stage and close the writer.
from_h5
classmethod
¶
from_h5(model_path: 'str | _Path', *, spec: 'DomainCaptureSpec', fem: 'FEMData', output: 'str | _Path', ops: Any = None) -> 'DomainCapture'
Construct a DomainCapture sourcing ndm / ndf from a model.h5.
Reads /meta/ndm and /meta/ndf from the supplied
model_path, resolves spec against fem using those
values, and returns a ready-to-use context manager writing
to output. Use this entry point when you have a saved
model.h5 but no live :class:apeSees bridge in the
current process (per Phase 9 D8 the user never types
ndm / ndf explicitly).
Parameters¶
model_path
Path to a bridge-emitted model.h5 whose /meta
carries ndm and ndf.
spec
Declarative :class:DomainCaptureSpec. Standalone (no
bridge attached) is fine — this method supplies
ndm / ndf from the file rather than from a bridge.
fem
The :class:FEMData to resolve selectors against. Must
correspond to the same mesh that produced model_path.
output
Path the resulting :class:DomainCapture will write to.
ops
Optional openseespy module (or test stand-in). Defaults
to lazy-loading openseespy.opensees.
Returns¶
DomainCapture Ready to be used as a context manager.
Source code in src/apeGmsh/results/capture/_domain.py
begin_stage ¶
Open a new stage. Returns the stage_id.
Source code in src/apeGmsh/results/capture/_domain.py
step ¶
Capture one snapshot at simulation time t.
Source code in src/apeGmsh/results/capture/_domain.py
end_stage ¶
Flush buffered data for the current stage to disk.
Multiple nodes records may target different node subsets
(e.g. displacements on all nodes + reactions on fixed nodes
only). The native schema has one _ids per partition, so
we merge: take the union of node IDs across records, fill
each component with NaN at slots the record didn't visit.
Source code in src/apeGmsh/results/capture/_domain.py
capture_modes ¶
Run ops.eigen() and write one mode-kind stage per mode.
n_modes defaults to the maximum across all modal
records in the spec. Pass an explicit value to override.
Source code in src/apeGmsh/results/capture/_domain.py
Inspect¶
apeGmsh.results._inspect.ResultsInspect ¶
results.inspect — what's available.
Source code in src/apeGmsh/results/_inspect.py
summary ¶
Multi-line human-readable summary.
Source code in src/apeGmsh/results/_inspect.py
components ¶
Available components per topology level for one stage.
If no stage is given, defaults to the only stage when there is exactly one; otherwise raises.
Source code in src/apeGmsh/results/_inspect.py
diagnose ¶
Explain where a component lives (or doesn't) in this stage.
When a viewer or downstream consumer asks for a component and
gets nothing back, this is the routing-side answer to "why
is the slab empty?". Walks every topology, calls each
composite's available_components(), and returns a
human-readable report that shows where component was
found and what's actually available at each level.
Parameters¶
component
Canonical component name (e.g. "axial_force",
"displacement_z", "stress_xx").
stage
Stage id or name. Defaults to the only stage when there
is exactly one.
Returns¶
str Multi-line report. Print it or include it in an error message.
Source code in src/apeGmsh/results/_inspect.py
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
Vocabulary¶
Canonical result names and shorthand expansion.
apeGmsh.results._vocabulary ¶
apeGmsh.results._vocabulary — deprecation shim (Phase 9).
The canonical vocabulary moved to :mod:apeGmsh._vocabulary so the
OpenSees bridge (declaration-side) and the results module
(consumer-side) can both import without a layering inversion.
This shim fires a :class:DeprecationWarning once on first import
and re-exports the canonical names for one release cycle. Internal
apeGmsh code imports from :mod:apeGmsh._vocabulary directly; only
external callers see the warning.
ALL_CANONICAL
module-attribute
¶
ALL_CANONICAL: frozenset[str] = frozenset(NODAL_KINEMATICS + NODAL_FORCES + PER_ELEMENT_NODAL_FORCES + LINE_DIAGRAMS + LINE_STATION_DEFORMATIONS + STRESS + STRAIN + DERIVED_SCALARS + FIBER + SPRING + MATERIAL_STATE)
expand_shorthand ¶
Expand a shorthand or pass through a canonical name.
Translational shorthands clip to ndm axes (e.g. ndm=2 →
displacement_x/y only). Rotational shorthands require
rotational DOFs in the active ndf and return () if there
are none. Tensor shorthands ("stress", "strain") clip to
3 components in ndm=2 (xx, yy, xy) and 6 in ndm=3.
Raises ValueError if name is neither a known shorthand
nor a canonical name.
Source code in src/apeGmsh/_vocabulary.py
is_canonical ¶
True if name is a known canonical component name.