Add ElementResultsPlotter.history_canonical for fiber/IP reduction - #98
Merged
Conversation
Fiber buckets (section.fiber.stress, section.fiber.strain) expand a
single engineering quantity into n_fibers * n_ip (or
n_fibers * n_layers * n_ip for layered shells) raw columns. Until now
the only way to plot a time history from one was to pick one specific
fiber*IP column via er.plot.history("sigma11_f3_ip0", ...). This adds
a sibling method that takes the canonical engineering name and folds
the matching columns with a chosen reduction.
API
---
ax, meta = er.plot.history_canonical(
canonical_name, # "strain_11", "stress_11", ...
*,
over="all", # "all" | "fibers" | "ips" | "layers"
reduce="mean", # mean | median | max | min | abs_max | sum
fiber_idx=None, ip_idx=None, layer_idx=None,
element_ids=None,
ax=None, x_axis="time",
annotate_stage_boundaries=True,
**plot_kwargs,
)
`over` declares which axis the reduction collapses; the others must be
pinned via the matching anchor when `over` is not "all" (e.g.
`over="fibers"` requires `ip_idx`). `meta["columns_used"]` lists which
raw columns were folded in, useful for audit.
Implementation factors the column-filter + reduction into two private
module-level helpers (_filter_canonical_columns, _reduce_fiber_ip) so
the regex matching and the dispatch table can be unit-tested in
isolation against synthetic DataFrames — no HDF5 fixture needed.
Tests
-----
* tests/unit/elements/test_history_canonical_reduce.py — 24 tests
covering: column filtering across the three META naming patterns
(compressed fibers, layered no-fibers, layered with fibers), all six
reduce ops with hand-computed expected values, fiber-anchor
substring disambiguation (_f1 vs _f10), every validation path.
* tests/integration/test_element_plotting.py — 5 end-to-end tests
against the solid_partition_dir section.fiber.stress bucket
(auto-skip in environments without the heavy fixture).
Docs
----
* docs/ElementResults.md — Plotting section updated with examples and
a paragraph on the over=/anchor pattern.
* docs/nodes_elements_cuts_plotting_guide.md — new comprehensive usage
guide covering nodes, elements, section cuts, and plotting (includes
history_canonical in §4.2).
Example
-------
* examples/solid_mixed_example.py — new section 11 slotted in right
after the "integrate_canonical doesn't work for fibers" section,
demonstrating all three over= modes and the missing-anchor error
path. Old 11/12/13 renumbered to 12/13/14; docstring and main()
updated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
er.plot.history_canonical(...)— a sibling to the existinger.plot.history(...)that takes a canonical engineering name (e.g."strain_11") and collapses the matching fiber / IP / layer columnswith a chosen reduction. One curve per element on the time axis.
Motivation
Fiber buckets (
section.fiber.stress,section.fiber.strain) expanda single quantity into
n_fibers × n_ip(orn_fibers × n_layers × n_ipfor layered shells) raw columns. Until now the only way to plotone was to pick a single fiber/IP column by name:
That's awkward when you actually want the mean over fibers, the
peak across IPs, or the max(|.|) across the whole cross-section.
What lands
overdeclares which axis the reduction collapses; the partneranchors become required when
over != "all"(e.g.over="fibers"needs
ip_idx=so the reduction collapses fibers at a fixed IPrather than silently folding in every IP too).
meta["columns_used"]lists the raw columns folded in — useful foraudit and downstream labelling.
metaotherwise mirrorshistory():x,y_per_element, plus areduced
seriesandstage_boundarieson multi-stage results.The reduction logic lives in two private module-level helpers
(
_filter_canonical_columns,_reduce_fiber_ip) so the regex matchingand the dispatch table are unit-testable in isolation — no HDF5
fixture needed.
Examples
Design decisions (locked with the user up front)
history)history(component=...)signature unambiguous; no canonical/raw name collision.Tests
tests/unit/elements/test_history_canonical_reduce.py— 24 new tests:every
over=mode against three column-naming patterns (compressedfibers, layered no-fibers, layered with fibers), all six reduce ops
with hand-computed expected values, fiber-anchor substring
disambiguation (
_f1vs_f10), every validation path.tests/integration/test_element_plotting.py— 5 new end-to-end testsagainst the
solid_partition_dirsection.fiber.stressbucket;auto-skip in environments without the heavy fixture (per existing
conftest conventions).
Locally: 125 passed, 6 skipped (skips are the new integration
tests on a fixture-less environment; everything else green).
Docs
docs/ElementResults.md— Plotting sectionupdated; the new method gets two example calls and a paragraph on
the
over=/ anchor pattern.docs/nodes_elements_cuts_plotting_guide.md— new comprehensive usage guide covering nodes, elements, section
cuts, and plotting (written earlier in the same session; includes
history_canonicalin §4.2).Example
examples/solid_mixed_example.py— new section 11 slotted in right after the
"
integrate_canonicaldoesn't work for fibers" section (the naturalnarrative complement), demonstrating all three
over=modes and themissing-anchor error path. Old 11/12/13 renumbered to 12/13/14;
module docstring and
main()updated.Versioning
This is a backward-compatible feature (MINOR per the repo's semver
policy). Not bumping
pyproject.tomlhere — past PRs (#95, #96) mergedwithout bumps and the version was rolled in a dedicated release PR
(#97). Same pattern applies here.
Follow-up flagged separately
While auditing docs I noticed
docs/elements_guide.mdcalls
er.plot.xy(...)in three places — butxy()only exists onNodalResults, notElementResults. That predates this PR and isout of scope; flagged as its own task chip.
🤖 Generated with Claude Code