Skip to content

Commit ec22ac3

Browse files
authored
VV: EbsdLib 3.0.0 + V&V of 6 Filters (#1631)
## ENH: Compute(Face)IPFColors filters Adds a "Color Key" ChoicesParameter to ComputeIPFColorsFilter and ComputeFaceIPFColoringFilter so pipelines can select between the three EbsdLib IPF coloring schemes per filter invocation: 0 = TSL (EDAX/OIM Analysis default -- preserved as default) 1 = PUCM (Patala perceptually-uniform color map) 2 = Nolze-Hielscher (MTEX HSV-style coloring) The choice index is mapped to ebsdlib::ColorKeyKind in executeImpl and threaded through the algorithm's InputValues struct + Impl-class constructor to the generateIPFColor(... kind) call site. Each LaueOps subclass already owns its own per-class TSL/PUCM/NH singletons sized to its rotation point group / fundamental sector, so no per-pixel allocation is added. ## ENH: WritePoleFigure Also fixes WritePoleFigure.cpp's templated `createIntensityPoleFigures` which previously called the 4-arg generateSphereCoordsFromEulers; the new EbsdLib API requires an explicit HexConvention. Passing config.hexConvention threads the existing PoleFigureConfiguration_t field down to the LaueOps call. Tests: - Existing TSL-regression tests stay green (default kind = TSL preserves byte-for-byte exemplar match). - New "ColorKey choice reaches algorithm" plumbing test per filter: runs the filter three times with k_ColorKey_Key = 0/1/2 into uniquely-named output arrays and asserts non-TSL kinds produce a different output than TSL. Catches any future off-by-one in the executeImpl switch without duplicating EbsdLib's per-Laue-class color correctness coverage. ## ENH: HexConvention ChoiceParameter on WritePoleFigure filter Pole-figure positions and corner labels for hex/trig phases differ by a 30° rotation about the c-axis between the two Cartesian basis conventions in EbsdLib (X||a vs X||a*). Pre-this-commit, the filter silently used PoleFigureConfiguration_t's default (X||a*) -- pipelines operating on EDAX/TSL/OIM Analysis data had no way to pick the convention that matches their input stack. Adds a "Hex/Trig Cartesian Basis Convention" ChoicesParameter: 0 = X parallel to a (EDAX/TSL/OIM Analysis -- new default) 1 = X parallel to a* (MTEX / Oxford / AZtec) Default is X||a because every released DREAM.3D / DREAM3DNX / SIMPL / SIMPLNX file stores hex/trig EulerAngles in this form by codebase guarantee (see ebsdlib::HexConvention doc comment in EbsdLibConstants.h). Cubic, tetragonal, orthorhombic, monoclinic, and triclinic phases ignore the parameter -- existing all-cubic test fixtures are unaffected by the default flip. The choice index is mapped to ebsdlib::HexConvention in executeImpl and threaded through WritePoleFigureInputValues to PoleFigureConfiguration_t::hexConvention, which the EbsdLib generateSphereCoordsFromEulers call already honors. Tests: - New "HexConvention choice reaches algorithm" plumbing test: runs the filter twice on the cubic exemplar with k_HexConvention_Key = 0 and = 1, captures the intensity arrays, and asserts they're identical (cubic is convention-invariant). Catches parameter wiring failures without depending on hex/trig exemplar data. * ENH: Pole Figure output is now a PNG file instead of a TIFF file. * BUG: WriteImageFilter preflight did not validate tuple dimensions * BUG: WritePoleFigure filter bug fixes for Hex convention and unit test updates * VER: Update to EbsdLib version 3.0.0 ## VV: Compute Feature Neighbor Misorientations & ComputeKernelAvgMisorientations Compute Kernel Average Misorientations fully V&V'ed Summary: - Confirmed no SIMPLNX-side bugs (legacy D2 inner-x-loop typo was corrected at port time); - documented 2 deviations from DREAM3D 6.5.171 (D1 EbsdLib 2.4.1 precision, D2 legacy kernel-bound typo); - retired 1 test (circular-oracle exemplar consumer regenerated from pre-EbsdLib-2.4.1 SIMPLNX output); - unit tests replaced with 5 inlined *Class 1 (Analytical) + Class 4 (Invariant)* test fixtures; - added 3 V&V source-tree deliverables (report, deviations, provenance); - fixed user-facing doc (pipeline-name typo, dropped orphan MassifPipeline reference, added EBSD_File_Processing examples). ## VV: Compute Feature Neighbor Misorientations Summary: - Found and fixed 1 bug (divisor clobbered inside inner j-loop of algorithm.cpp); - documented 2 deviations from DREAM3D 6.5.171 (D1 divisor bug, D2 EbsdLib 2.4.1 precision); - retired 2 tests (circular-oracle exemplar consumer + UNIMPLEMENTED stub); - unit tests replaced with 4 inlined *Class 1 (Analytical) + Class 4 (Invariant)* test fixtures; - added 3 V&V source-tree deliverables (report, deviations, provenance); - fixed pipeline-name typo in user-facing doc. Signed-off-by: Michael Jackson <mike.jackson@bluequartz.net> ## VV: BadDataNeighborOrientationCheck + ComputeFeatureFaceMisorientation V&V'ed BadDataNeighborOrientationCheck: - Confirmed no SIMPLNX-side bugs (D1 was landed pre-V&V in PR #1499; D2 was SIMPLNX-correct from rewrite onward); - documented 2 deviations from DREAM3D 6.5.171 (D1 iterative-decay loop bound `>` should be `>=`, D2 stale-w threshold check leaks across different-phase neighbors); - retired 1 test (legacy 6_6 exemplar-comparison TEST_CASE — replaced with the engineer's hand-derived 27-fixture dataset); - unit tests replaced with 27 hand-derived Class 1 (Analytical) base fixtures + 18 Class 4 (Invariant) Invariants-Sweep DYNAMIC_SECTIONs + 1 Class 4 Idempotence test + 1 inlined 2D Image fixture (31 TEST_CASEs / 49 ctest entries, 100% pass); - added 3 V&V source-tree deliverables (report, deviations, provenance); - restored bad_data_neighbor_orientation_check_v2.tar.gz archive download in test/CMakeLists.txt. Compute Feature Face Misorientation: - Confirmed no SIMPLNX-side bugs (D3 fix corrects a legacy 6.5.171 bug — SIMPLNX has been correct since the rewrite); - documented 4 deviations from DREAM3D 6.5.171 (D1 9 additional Laue classes now supported, D2 1-component magnitude output vs legacy 3-component axis·angle, D3 NaN sentinel for unprocessed faces vs legacy implicit 0, D4 EbsdLib 2.4.1 CubicOps precision improvement); - retired 1 test ("Invalid filter execution" — preflight-failure paths made unreachable by D3's NaN-on-invalid-face semantics); - unit tests replaced with 1 hand-built Class 1 (Analytical) 37-fixture dataset (30 normal cases across all 11 EbsdLib Laue classes × 3 pure-φ1 boundaries + 4 edge cases + 3 Trigonal_High cases) + 1 SIMPL 6.4/6.5 backwards-compat; - added 3 V&V source-tree deliverables (report, deviations, provenance); - fixed user-facing doc. ## VV: Compute Feature Neighbor C-Axis Misalignments fully V&V'ed Summary: - Found and fixed 1 bug (divisor clobbered inside inner j-loop of algorithm.cpp, sibling of F#2's D1 — production-relevant via shipping EBSD_Hexagonal_Data_Analysis.d3dpipeline which runs with find_avg_misals=true); - documented 5 deviations from DREAM3D 6.5.171 (D1 divisor bug, D2 avg-array fillValue uncertainty (latent, confirmed dormant on current backend), D4 EbsdLib quat-matrix swap precision drift, D5 PR #1438 preflight-banner UX downgrade, D6 Hexagonal_Low support gap); - retired 1 test (hex-only exemplar consumer — could not trigger the divisor bug; removed its download_test_data line from test/CMakeLists.txt); - unit tests replaced with 4 inlined Class 1 (Analytical) + Class 4 (Invariant) test fixtures (incl. a 10x10x1 6-feature realistic microstructure with 3 bug-exposing per-feature configurations); - added 3 V&V source-tree deliverables (report, deviations, provenance); - performed empirical A/B against 3 binaries (DREAM3D 6.5.171 official, 6.5.172 with D1+D4+D6 backports, SIMPLNX) and confirmed byte-for-byte match between 6.5.172 (post-backport) and SIMPLNX — 24/24 values bit-identical. Artifacts at /Users/mjackson/Desktop/F6_AB_Test/; - fixed Hexagonal_Low note in user-facing doc. Signed-off-by: Michael Jackson <mike.jackson@bluequartz.net> ## VV: Compute Grouping Density fully V&V'ed Summary: - Confirmed no SIMPLNX-side bugs (clean Port; algorithm verified correct as-is — only cleanup applied: [SimplnxReview]→[SimplnxCore] test-tag fix on 7 tests + code-comment cleanup in the algorithm + filter source); - documented 0 deviations from the pre-SIMPLNX legacy (legacy is the un-merged `tuks188/DREAM3D` `feature/770_Grouping_Density` branch, not 6.5.171 shipped); empirical A/B against a locally-rebuilt legacy binary produced BIT-IDENTICAL output across all 4 (UseNonContiguous, FindCheckedFeatures) configurations of both GroupingDensities and CheckedFeatures; - retired 5 tests (4 redundant execution tests + 1 v1-exemplar consumer); v1 archive `compute_grouping_densities.tar.gz` removed from test/CMakeLists.txt; - unit tests replaced with 1 DYNAMIC_SECTION 4-config exemplar A/B test (Class 1 Analytical + Class 4 Invariant oracles, hand-derivation in the V&V report) + 1 Class 4 empty-parent sentinel test (-1.0f sentinel) + 1 preflight-error -15672 test (gap closed); 3 existing preflight error tests + 1 SIMPL backwards-compat test retained — 7 TEST_CASEs total; - added 2 V&V source-tree deliverables (report, deviations); provenance materially captured in the v2 archive's inline ReadMe + comparison report rather than a separate vv/provenance/ file (the v2 tarball contains input + all 4 legacy and SIMPLNX outputs + comparison script + sign-off ReadMe); - published new `compute_grouping_densities_v2.tar.gz` to the GitHub Data_Archive release (SHA512 wired into test/CMakeLists.txt) with hand-review sign-off ReadMe; - updated user-facing doc (Required Input Sources w/ MyST cross-links, explicit volume units, tie-break behavior, italicized -1.0 sentinel) and added a new ComputeGroupingDensity_Infographic (PNG + SVG); small core-DataStructure header cleanup (IListStore/ListStore/EmptyListStore/AbstractListStore — `uint64`→`usize` consistency + virtual `size()`). Signed-off-by: Michael Jackson <mike.jackson@bluequartz.net> ## VV: Compute Average C-Axis Orientations fully V&V'ed Summary: - Confirmed no SIMPLNX-side bugs (algorithm verified correct as-is); applied 2 algorithm refinements during the Phase-7 review (counter==0 → NaN at finalize + final per-feature normalize) — these are intentional design alignments that surface as D1 and D2 deviations vs DREAM3D 6.5.171 but match the intended algorithm and are bit-identical to the 6.5.172 backport; - documented 2 deviations from DREAM3D 6.5.171 (D1 counter==0 → NaN at finalize replaces legacy's (0,0,1) rescue at F0/F5/F6; D2 precision-sensitive direction + unit-vector vs unnormalized magnitude at F7 antipodal-flip cancellation boundary); - retired 1 test (legacy-by-reputation exemplar consumer of 7_2_AvgCAxis.tar.gz — confirmed circular oracle per policy line 33: reference values were produced by a "special build of DREAM3D 6.6.379 with micro-texture bug fixes," not by an independent oracle); - unit tests replaced with 3 tests: 1 Class 1 (Analytical) valid-execution exemplar against a hand-built 11-cell/8-feature dataset + 1 negative all-non-hex error test + 1 SIMPL 6.4/6.5 backwards-compat DYNAMIC_SECTION — covers 8/12 enumerated code paths (gaps: all-hex-ensemble preflight, background-voxel skip, 2 cancel-check paths); - added 3 V&V source-tree deliverables (report, deviations, provenance — provenance file attributes the dataset design to MAJ with subsequent design changes and Python generation-script integration by Claude Opus 4.7, signed off by MAJ); - published new compute_avg_c_axis.tar.gz (replaces retired 7_2_AvgCAxis.tar.gz) with hand-built Class 1 dataset + Class 4 (Invariant) ||AvgCAxes|| == 1.0 unit-vector contract for F7; empirical three-way A/B (SIMPLNX vs 6.5.171 official vs 6.5.172 backport) confirmed SIMPLNX bit-identical to 6.5.172 across all 8 features, conclusively isolating D1 and D2 root causes; - updated user-facing doc with new ComputeAvgCAxes_HexagonalCAxis figure (SVG + PNG) explaining the c-axis-in-sample-frame convention. Signed-off-by: Michael Jackson <mike.jackson@bluequartz.net> --------- Signed-off-by: Michael Jackson <mike.jackson@bluequartz.net>
1 parent 7cff7f2 commit ec22ac3

86 files changed

Lines changed: 6571 additions & 1414 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cmake/Plugin.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,14 @@ function(create_simplnx_plugin_unit_test)
372372
#------------------------------------------------------------------------------
373373
# Require that the test plugins are built before tests because some tests
374374
# require loading from those plugins but don't want to link to them.
375+
#------------------------------------------------------------------------------
375376
add_dependencies(${UNIT_TEST_TARGET} ${ARGS_PLUGIN_NAME})
376377

378+
#------------------------------------------------------------------------------
379+
# Require all test files be downloaded first before running tests
380+
#------------------------------------------------------------------------------
381+
add_dependencies(${UNIT_TEST_TARGET} Fetch_Remote_Data_Files)
382+
377383
set_target_properties(${UNIT_TEST_TARGET}
378384
PROPERTIES
379385
RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:simplnx>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# V&V Commit Message Template
2+
3+
This is the standard commit message format for landing a completed V&V cycle on a SIMPLNX filter. It is used by the engineer at Phase 13 (status flip DRAFT → READY FOR REVIEW / COMPLETE), and is the commit that opens the PR.
4+
5+
## Format
6+
7+
```
8+
VV: <Filter Human Name> fully V&V'ed
9+
10+
Summary:
11+
- Found and fixed <N> bug(s) (<one-line per bug, or "Confirmed no bugs">);
12+
- documented <M> deviation(s) from DREAM3D 6.5.171 (<D1 …, D2 …>);
13+
- retired <P> tests (<reason: circular oracle / UNIMPLEMENTED stub / etc., or "none">);
14+
- unit tests replaced with <Q> inlined *<Class X (Name) + Class Y (Name)>* test fixtures;
15+
- added 3 V&V source-tree deliverables (report, deviations, provenance);
16+
- <optional: doc/pipeline-name fixes, when applicable>.
17+
```
18+
19+
## Title rules
20+
21+
- Must start with `VV:` (matches existing precedent — e.g., commit `99f3a9865` for `Compute Feature Reference Misorientations`).
22+
- Use the filter's `humanName()` from the `.cpp` (with spaces, not the class name).
23+
- End with `fully V&V'ed`. If the cycle is partial (rare — e.g., second-engineer oracle review still pending), end with `— READY FOR REVIEW` instead.
24+
25+
## Body rules
26+
27+
- One bullet per category, even when the count is zero. **Don't drop bullets** — write "Confirmed no bugs" or "no tests retired" so the reader knows the question was asked.
28+
- Past-tense verbs at the start of each bullet ("Found and fixed", "documented", "retired", "replaced", "added", "fixed").
29+
- Semicolons at the end of each bullet except the last (period on the last).
30+
- Inline the deviation IDs (`D1`, `D2`, …) with a 2-3 word reminder of what each one was. The full text lives in `vv/deviations/<FilterName>.md`; the commit message just needs to be greppable.
31+
- Oracle classes get the parenthetical name (`Class 1 (Analytical)`, `Class 4 (Invariant)`). See `oracle_classes.md` for the canonical class list.
32+
- The "3 V&V source-tree deliverables" line is invariant across all V&V commits (every cycle produces exactly those 3). Don't rewrite it per-filter.
33+
34+
## Worked example
35+
36+
This is what the F#2 (`ComputeFeatureNeighborMisorientations`) V&V cycle's commit looks like:
37+
38+
```
39+
VV: Compute Feature Neighbor Misorientations fully V&V'ed
40+
41+
Summary:
42+
- Found and fixed 1 bug (divisor clobbered inside inner j-loop of algorithm.cpp);
43+
- documented 2 deviations from DREAM3D 6.5.171 (D1 divisor bug, D2 EbsdLib 2.4.1 precision);
44+
- retired 2 tests (circular-oracle exemplar consumer + UNIMPLEMENTED stub);
45+
- unit tests replaced with 4 inlined *Class 1 (Analytical) + Class 4 (Invariant)* test fixtures;
46+
- added 3 V&V source-tree deliverables (report, deviations, provenance);
47+
- fixed pipeline-name typo in user-facing doc.
48+
```
49+
50+
## When a category is zero or N/A
51+
52+
| Situation | Bullet phrasing |
53+
|----------------------------------------------------|-----------------------------------------------------------------------|
54+
| Clean Port, no bugs found | `Confirmed no bugs (clean Port);` |
55+
| No deviations from legacy | `Confirmed no deviations from DREAM3D 6.5.171;` |
56+
| Fresh V&V, no prior tests to retire | `No prior tests retired (fresh V&V cycle);` |
57+
| Existing tests kept, only new ones added | `Augmented existing tests with <Q> inlined …;` |
58+
| Doc was already correct | *omit the last bullet entirely (it's the only optional one)* |
59+
| New filter, no legacy equivalent | `documented 0 deviations (no legacy equivalent — new filter);` |
60+
61+
## Why this format
62+
63+
- **Scannable.** A reviewer skimming `git log` should be able to decide whether a V&V commit is worth opening from the title and one bullet pass.
64+
- **Greppable.** `git log --grep='^VV:'` returns every V&V commit. `git log --grep='D2 EbsdLib'` returns every commit that mentions the EbsdLib precision deviation. The deviation IDs are stable across commits (per the `<FilterName>-D<N>` rule in `deviation_template.md`).
65+
- **Constrained.** The five fixed categories (bugs / deviations / retired tests / new fixtures / V&V deliverables) match what every V&V cycle produces under the v2 policy. The engineer fills slots rather than designing prose.
66+
- **Cross-references the source-tree deliverables.** The commit is the "shortest legible record" of the V&V; the long-form analysis lives at `src/Plugins/<Plugin>/vv/{,deviations/,provenance/}<FilterName>.md`. A reader who wants more clicks through.

docs/vv_templates/oracle_classes.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ The five classes differ in **what they trust** (math, a library, a paper, proper
1010

1111
## Class 1 — Analytical
1212

13-
**What it is:** You can write down, on paper, the *exact* expected output as a closed-form function of the input. The math is small enough to do by hand or in a spreadsheet on a toy dataset.
13+
**What it is:** You can write down, on paper, the *exact* expected output as a closed-form function of the input. The math is small enough to do by hand or in a spreadsheet on a hand-built fixture.
1414

1515
**Where the trust comes from:** Mathematics itself. Arithmetic doesn't drift. `2 + 2 == 4` today, tomorrow, and forever.
1616

@@ -32,10 +32,20 @@ The five classes differ in **what they trust** (math, a library, a paper, proper
3232
**Weaknesses:**
3333

3434
- Only works when the algorithm has a tractable closed form on small inputs. Many real algorithms don't (e.g., segmentation, optimization, iterative convergence).
35-
- Toy datasets may not exercise all code paths in a complex filter.
35+
- Hand-built fixtures may not exercise all code paths in a complex filter.
3636

3737
**How it's encoded in tests:** Usually inline `REQUIRE(result == 0.6428571)` with a comment showing the hand derivation. Or a tiny exemplar `.dream3d` whose values were hand-computed and the `.dream3d` is just a cache of the computation.
3838

39+
### Naming convention: `AnalyticalFixtures`
40+
41+
The C++ namespace used to hold Class 1 test scaffolding (helpers, struct, fixture builders) is `AnalyticalFixtures` — e.g., `AnalyticalFixtures::CreateScaffold`, `AnalyticalFixtures::FixtureData`.
42+
43+
**Why not `ToyFixtures`?** In CS / ML / testing terminology, "toy example" is the established term for a minimal hand-crafted dataset with a closed-form expected output. It is a precise technical signal — not dismissive — meaning *"this is an analytical oracle, not a regression-on-real-data circular oracle."* The original V&V scaffolding used `ToyFixtures` on those grounds.
44+
45+
**Why `AnalyticalFixtures` then?** SIMPLNX V&V deliverables read to a non-CS-academic audience (SBIR program managers, MTR reviewers, materials engineers). To that audience, "toy" can read as informal or unrigorous — the exact perception V&V is meant to dispel. `AnalyticalFixtures` preserves the load-bearing signal that "Toy" was carrying (*Class 1 closed-form oracle data*) without the dismissive connotation.
46+
47+
The rename was applied 2026-06-10 across all test files, V&V reports, deviations, provenance docs, and templates. The decision is documented here so it doesn't get re-litigated.
48+
3949
## Class 2 — Reference implementation
4050

4151
**What it is:** A trusted external library — one with broader user base, more testing, and longer history than your filter — computes the same operation on the same input. Its output becomes your expected output.
@@ -50,7 +60,7 @@ The five classes differ in **what they trust** (math, a library, a paper, proper
5060
- Eigen for linear algebra in C++ tests.
5161
- A reference Python implementation of an algorithm published as a research paper companion.
5262

53-
**Workflow:** Write a small Python (or other) script that takes the toy input, runs the reference library, and saves the expected output. That script + the library version + any random seed used become part of the V&V archive. Future tests load the saved expected output and compare bit-for-bit (or with appropriate float tolerance).
63+
**Workflow:** Write a small Python (or other) script that takes the hand-built input, runs the reference library, and saves the expected output. That script + the library version + any random seed used become part of the V&V archive. Future tests load the saved expected output and compare bit-for-bit (or with appropriate float tolerance).
5464

5565
**Strengths:**
5666

@@ -216,7 +226,7 @@ If the existing exemplar in the data archive was generated from one of the above
216226

217227
| Class | Name | Best for | Default choice when |
218228
|---|---|---|---|
219-
| 1 | Analytical | Tight algorithms with closed-form output, hand-pickable toy inputs, small outputs | The math is short enough to do on paper |
229+
| 1 | Analytical | Tight algorithms with closed-form output, hand-pickable hand-built inputs, small outputs | The math is short enough to do on paper |
220230
| 2 | Reference impl | Algorithms where a trusted library exists and you trust it more than your own implementation | You're porting an algorithm that has a well-known library implementation elsewhere |
221231
| 3 | Paper-based | Implementations of published algorithms (orientation math, classical algorithms with named authors) | The filter's header cites a paper |
222232
| 4 | Invariant | Anything with conservation laws, range bounds, or structural constraints | Always — add Class 4 alongside whatever other class you pick |

docs/vv_templates/report_gates.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ The dashboard a reviewer reads first. Lets a reviewer decide in 30 seconds wheth
4848
For detailed explanations of each class — with examples, strengths and weaknesses, drift-risk analysis, and a decision tree for picking the right class — see [`oracle_classes.md`](./oracle_classes.md). The summary below is the gate checklist.
4949

5050
- [ ] Class named (1–5)
51-
- 1 = Analytical (closed-form expected output on toy input)
51+
- 1 = Analytical (closed-form expected output on hand-built input)
5252
- 2 = Reference implementation (NumPy / SciPy / MTEX / EbsdLib upstream)
5353
- 3 = Paper-based (published figure / table / equation)
5454
- 4 = Invariant-based (derivable property the output must satisfy)

docs/vv_templates/vv_policy.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Every filter must be verified against at least one of the following. Classes 1
2424

2525
| # | Class | What it is | Drift risk |
2626
|---|---|---|---|
27-
| 1 | Analytical | Closed-form expected output on toy input (threshold, crop, rotate, color conversion, array arithmetic) | None |
27+
| 1 | Analytical | Closed-form expected output on hand-built input (threshold, crop, rotate, color conversion, array arithmetic) | None |
2828
| 2 | Reference implementation | Trusted external library produces the expected output (NumPy / SciPy / MTEX / EbsdLib upstream / Eigen) | **High** — library version drift |
2929
| 3 | Paper-based | Filter reproduces a published figure, table, or equation from a named reference | Low–Medium |
3030
| 4 | Invariant | Derivable properties the output must satisfy (FeatureIds start at 1 and contiguous; sum of phase fractions = 1; mass conservation) | None |
@@ -56,6 +56,7 @@ The verified state is pinned by **(commit hash, archive SHA512)**. The commit ca
5656
| [`report_gates.md`](./report_gates.md) | Per-section "Done when:" checklists — reference while filling in the report |
5757
| [`deviation_template.md`](./deviation_template.md) | Empty deviation file — copy into `src/Plugins/<P>/vv/deviations/<FilterName>.md` |
5858
| [`provenance_template.md`](./provenance_template.md) | Empty exemplar-provenance sidecar — copy per exemplar archive |
59+
| [`commit_template.md`](./commit_template.md) | Standard commit message format for landing a completed V&V cycle — use at step 6 of the engineer workflow below |
5960

6061
## Engineer workflow
6162

@@ -64,7 +65,7 @@ The verified state is pinned by **(commit hash, archive SHA512)**. The commit ca
6465
3. Run `python scripts/vv_init.py <FilterName>` to scaffold the report and deviation files in the plugin tree.
6566
4. Open `report_gates.md` in a second tab.
6667
5. Work each section in any order. A section is "done" when all its gates pass.
67-
6. When all gates green, set `Status: READY FOR REVIEW`, push a `vv/<FilterName>` branch.
68+
6. When all gates green, set `Status: READY FOR REVIEW`, push a `vv/<FilterName>` branch with a commit following [`commit_template.md`](./commit_template.md).
6869
7. After sign-off, set `Status: COMPLETE`. Verified commit hash is filled in at SBIR deliverable assembly.
6970

7071
## Status tracking across filters

src/Plugins/OrientationAnalysis/docs/BadDataNeighborOrientationCheckFilter.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,18 @@ changing voxels.
3535
### 2D Versus 3D Note
3636

3737
If the user is processing a 2D data set, **none** of the voxels can have 6 neighbors
38-
since there are no neighbors is the +-Z directions.
38+
since there are no neighbors in the +/-Z directions.
3939

4040
### Warning - Data Modification
4141

4242
Only the *Mask* value defining the cell as *good* or *bad* is changed. No other cell level array is modified.
4343

44+
### Memory Considerations
45+
46+
The filter allocates a temporary `int32` neighbor-count array sized to the total voxel count
47+
(4 bytes per voxel). For a 1-billion-voxel dataset, that is approximately 4 GB of additional
48+
working memory during execution. This memory is released when the filter finishes.
49+
4450
## Example Data
4551

4652
| Example Input Image | Example Output Image |
@@ -55,8 +61,12 @@ From the above before and after images you can see that this filter can help mod
5561
## Example Pipelines
5662

5763
+ (02) Small IN100 Full Reconstruction
58-
+ INL Export
59-
+ 04_Steiner Compact
64+
65+
## Related Filters
66+
67+
- [Fill Bad Data](../SimplnxCore/FillBadDataFilter.md) — fills voxels still marked bad after this filter runs (or as a standalone alternative when no orientation data is available).
68+
- [Multi-Threshold Objects](../SimplnxCore/MultiThresholdObjectsFilter.md) — typical upstream filter that generates the initial *Mask* array (e.g., from `Confidence Index` and `Image Quality`).
69+
- [Replace Element Attributes with Neighbor Values](../SimplnxCore/ReplaceElementAttributesWithNeighborValuesFilter.md) — alternative cleanup approach that copies attribute values from neighboring cells rather than flipping a mask.
6070

6171
## License & Copyright
6272

src/Plugins/OrientationAnalysis/docs/ComputeAvgCAxesFilter.md

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,44 @@ Statistics (Crystallography)
66

77
## Description
88

9-
This **Filter** determines the average C-axis location of each **Feature** by the following algorithm:
9+
This **Filter** computes the average C-axis direction for each **Feature** (grain) in hexagonal materials. The result is a unit vector per **Feature** that indicates where the grain's C-axis points in the sample reference frame.
1010

11-
1. Gather all **Elements** that belong to the **Feature**
12-
2. Determine the location of the c-axis in the sample *reference frame* for the rotated quaternions for all **Elements**. This is achieved by converting the input quaternion to
13-
an orientation matrix (which represents a passive transform matrix), taking the transpose of the matrix to convert it from passive to active, and then multiplying the
14-
transposed matrix by the crystallographic C-Axis direction vector <001>.
15-
3. Average the locations and store the average for the **Feature**
11+
### What is the C-Axis?
1612

17-
*Note:* This **Filter** will only work properly for *Hexagonal* materials. The **Filter** does not apply any symmetry
18-
operators because there is only one c-axis (<001>) in *Hexagonal* materials and thus all symmetry operators will leave
19-
the c-axis in the same position in the sample *reference frame*. However, in *Cubic* materials, for example, the {100}
20-
family of directions are all equivalent and the <001> direction will change location in the sample *reference frame* when
21-
symmetry operators are applied.
13+
In hexagonal crystal structures (such as titanium, magnesium, and zinc), the *C-axis* is the unique crystallographic direction that runs along the long axis of the hexagonal unit cell (the [001] direction). This axis is important because many mechanical and physical properties of hexagonal materials vary depending on whether they are measured along or perpendicular to the C-axis.
2214

23-
This filter will error out if **ALL** phases are non-hexagonal. Any non-hexagonal phases will have their computed values set to NaN value.
15+
![Fig. 1: The C-axis in a hexagonal unit cell.](Images/ComputeAvgCAxes_HexagonalCAxis.png)
2416

25-
The output is a direction vector for each feature.
17+
### How This Filter Works
18+
19+
Each **Cell** (voxel) in a grain has its own measured orientation. This filter determines where each cell's C-axis points in the physical sample coordinate system, then averages those directions across all cells belonging to the same **Feature**:
20+
21+
1. For each **Cell**, the filter uses the cell's orientation (quaternion) to rotate the crystal [001] direction into the sample reference frame.
22+
2. The rotated C-axis directions are accumulated for each **Feature**, ensuring all directions point into the same hemisphere for a consistent average.
23+
3. The accumulated directions are normalized to produce a unit vector for each **Feature**.
24+
25+
### Hexagonal Materials Only
26+
27+
This filter only produces valid results for hexagonal phases (6/mmm or 6/m symmetry). In hexagonal materials, the C-axis is unique -- there is only one [001] direction, so crystal symmetry does not create ambiguity.
28+
29+
In cubic materials, the [001], [010], and [100] directions are all crystallographically equivalent. Applying symmetry operators would move the [001] direction to different positions in the sample frame, making a simple average meaningless. For this reason, the filter **silently skips non-hexagonal cells** during accumulation. A **Feature** whose contributing cells are *all* non-hexagonal (or which has no cells assigned to it at all) will have its output set to **NaN**.
30+
31+
The filter will produce an error if no hexagonal phases are present in the data (`-76402`: "No phases that have a crystal symmetry of Hexagonal (6/mmm or 6/m) were found.").
32+
33+
### Required Input Sources
34+
35+
This filter operates on previously segmented data and requires that several prior operations have already been run:
36+
37+
- **Cell Quaternions** -- typically read from EBSD data via [Read H5EBSD](ReadH5EbsdFilter.md), [Read CTF Data](ReadCtfDataFilter.md), or [Read ANG Data](ReadAngDataFilter.md); can also be produced from Euler angles by [Convert Orientations](ConvertOrientationsFilter.md).
38+
- **Cell Feature Ids** -- produced by a segmentation filter such as [Segment Features (Misorientation)](EBSDSegmentFeaturesFilter.md) or [Segment Features (C-Axis Misalignment)](CAxisSegmentFeaturesFilter.md).
39+
- **Cell Phases** -- typically read from EBSD data alongside the quaternions.
40+
- **Crystal Structures** -- ensemble-level array read from EBSD data or created by [Create Ensemble Info](CreateEnsembleInfoFilter.md).
2641

2742
% Auto generated parameter table will be inserted here
2843

2944
## Example Pipelines
3045

31-
EBSD_Hexagonal_Data_Analysis
46+
+ `EBSD_Hexagonal_Data_Analysis`
3247

3348
## License & Copyright
3449

0 commit comments

Comments
 (0)