Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions cmake/Plugin.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,14 @@ function(create_simplnx_plugin_unit_test)
#------------------------------------------------------------------------------
# Require that the test plugins are built before tests because some tests
# require loading from those plugins but don't want to link to them.
#------------------------------------------------------------------------------
add_dependencies(${UNIT_TEST_TARGET} ${ARGS_PLUGIN_NAME})

#------------------------------------------------------------------------------
# Require all test files be downloaded first before running tests
#------------------------------------------------------------------------------
add_dependencies(${UNIT_TEST_TARGET} Fetch_Remote_Data_Files)

set_target_properties(${UNIT_TEST_TARGET}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:simplnx>
Expand Down
66 changes: 66 additions & 0 deletions docs/vv_templates/commit_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# V&V Commit Message Template

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.

## Format

```
VV: <Filter Human Name> fully V&V'ed

Summary:
- Found and fixed <N> bug(s) (<one-line per bug, or "Confirmed no bugs">);
- documented <M> deviation(s) from DREAM3D 6.5.171 (<D1 …, D2 …>);
- retired <P> tests (<reason: circular oracle / UNIMPLEMENTED stub / etc., or "none">);
- unit tests replaced with <Q> inlined *<Class X (Name) + Class Y (Name)>* test fixtures;
- added 3 V&V source-tree deliverables (report, deviations, provenance);
- <optional: doc/pipeline-name fixes, when applicable>.
```

## Title rules

- Must start with `VV:` (matches existing precedent — e.g., commit `99f3a9865` for `Compute Feature Reference Misorientations`).
- Use the filter's `humanName()` from the `.cpp` (with spaces, not the class name).
- 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.

## Body rules

- 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.
- Past-tense verbs at the start of each bullet ("Found and fixed", "documented", "retired", "replaced", "added", "fixed").
- Semicolons at the end of each bullet except the last (period on the last).
- 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.
- Oracle classes get the parenthetical name (`Class 1 (Analytical)`, `Class 4 (Invariant)`). See `oracle_classes.md` for the canonical class list.
- 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.

## Worked example

This is what the F#2 (`ComputeFeatureNeighborMisorientations`) V&V cycle's commit looks like:

```
VV: Compute Feature Neighbor Misorientations fully V&V'ed

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.
```

## When a category is zero or N/A

| Situation | Bullet phrasing |
|----------------------------------------------------|-----------------------------------------------------------------------|
| Clean Port, no bugs found | `Confirmed no bugs (clean Port);` |
| No deviations from legacy | `Confirmed no deviations from DREAM3D 6.5.171;` |
| Fresh V&V, no prior tests to retire | `No prior tests retired (fresh V&V cycle);` |
| Existing tests kept, only new ones added | `Augmented existing tests with <Q> inlined …;` |
| Doc was already correct | *omit the last bullet entirely (it's the only optional one)* |
| New filter, no legacy equivalent | `documented 0 deviations (no legacy equivalent — new filter);` |

## Why this format

- **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.
- **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`).
- **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.
- **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.
3 changes: 2 additions & 1 deletion docs/vv_templates/vv_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ The verified state is pinned by **(commit hash, archive SHA512)**. The commit ca
| [`report_gates.md`](./report_gates.md) | Per-section "Done when:" checklists — reference while filling in the report |
| [`deviation_template.md`](./deviation_template.md) | Empty deviation file — copy into `src/Plugins/<P>/vv/deviations/<FilterName>.md` |
| [`provenance_template.md`](./provenance_template.md) | Empty exemplar-provenance sidecar — copy per exemplar archive |
| [`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 |

## Engineer workflow

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

## Status tracking across filters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,18 @@ changing voxels.
### 2D Versus 3D Note

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

### Warning - Data Modification

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

### Memory Considerations

The filter allocates a temporary `int32` neighbor-count array sized to the total voxel count
(4 bytes per voxel). For a 1-billion-voxel dataset, that is approximately 4 GB of additional
working memory during execution. This memory is released when the filter finishes.

## Example Data

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

+ (02) Small IN100 Full Reconstruction
+ INL Export
+ 04_Steiner Compact

## Related Filters

- [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).
- [Multi-Threshold Objects](../SimplnxCore/MultiThresholdObjectsFilter.md) — typical upstream filter that generates the initial *Mask* array (e.g., from `Confidence Index` and `Image Quality`).
- [Replace Element Attributes with Neighbor Values](../SimplnxCore/ReplaceElementAttributesWithNeighborValuesFilter.md) — alternative cleanup approach that copies attribute values from neighboring cells rather than flipping a mask.

## License & Copyright

Expand Down
43 changes: 29 additions & 14 deletions src/Plugins/OrientationAnalysis/docs/ComputeAvgCAxesFilter.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,44 @@ Statistics (Crystallography)

## Description

This **Filter** determines the average C-axis location of each **Feature** by the following algorithm:
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.

1. Gather all **Elements** that belong to the **Feature**
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
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
transposed matrix by the crystallographic C-Axis direction vector <001>.
3. Average the locations and store the average for the **Feature**
### What is the C-Axis?

*Note:* This **Filter** will only work properly for *Hexagonal* materials. The **Filter** does not apply any symmetry
operators because there is only one c-axis (<001>) in *Hexagonal* materials and thus all symmetry operators will leave
the c-axis in the same position in the sample *reference frame*. However, in *Cubic* materials, for example, the {100}
family of directions are all equivalent and the <001> direction will change location in the sample *reference frame* when
symmetry operators are applied.
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.

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

The output is a direction vector for each feature.
### How This Filter Works

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**:

1. For each **Cell**, the filter uses the cell's orientation (quaternion) to rotate the crystal [001] direction into the sample reference frame.
2. The rotated C-axis directions are accumulated for each **Feature**, ensuring all directions point into the same hemisphere for a consistent average.
3. The accumulated directions are normalized to produce a unit vector for each **Feature**.

### Hexagonal Materials Only

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.

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**.

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.").

### Required Input Sources

This filter operates on previously segmented data and requires that several prior operations have already been run:

- **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).
- **Cell Feature Ids** -- produced by a segmentation filter such as [Segment Features (Misorientation)](EBSDSegmentFeaturesFilter.md) or [Segment Features (C-Axis Misalignment)](CAxisSegmentFeaturesFilter.md).
- **Cell Phases** -- typically read from EBSD data alongside the quaternions.
- **Crystal Structures** -- ensemble-level array read from EBSD data or created by [Create Ensemble Info](CreateEnsembleInfoFilter.md).

% Auto generated parameter table will be inserted here

## Example Pipelines

EBSD_Hexagonal_Data_Analysis
+ `EBSD_Hexagonal_Data_Analysis`

## License & Copyright

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ There are 2 outputs from this filter:

### Notes

**NOTE:** Only features with identical phase values and a crystal structure of **Hexagonal_High** will be calculated. If two features have different phase values or a crystal structure that is *not* Hexagonal_High then a value of NaN is set for the misorientation.
**NOTE:** Only features with identical phase values and a crystal structure of **Hexagonal_High** (6/mmm) or **Hexagonal_Low** (6/m) will be calculated. If two features have different phase values, or if the shared phase has a crystal structure that is not one of the two hexagonal Laue classes, then a value of NaN is set for the misalignment.

Results from this filter can differ from its original version in DREAM.3D 6.5.171 by around 0.0001. This version uses double precision and Eigen for matrix operations which account for the differences in output.
Results from this filter can differ from its original version in DREAM.3D 6.5.171 by around 0.0001 degrees. This version uses double precision and Eigen for matrix operations which account for the differences in output.

% Auto generated parameter table will be inserted here

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The user can also calculate the average misorientation between the feature and a

## Example Pipelines

+ (05) SmallIN100 Crystallographic Statistics
+ (04) Small IN100 Crystallographic Statistics

## License & Copyright

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ This **Filter** determines the Kernel Average Misorientation (KAM) for each **Ce
1. Calculate the misorientation angle between each **Cell** in a kernel and the central **Cell** of the kernel
2. Average all of the misorientations for the kernel and store at the central **Cell**

The calculation will **not** consider cells that belong to different 'feature Ids', ie.e, different grains.
The calculation will **not** consider cells that belong to different 'feature Ids', i.e., different grains.

*Note:* All **Cells** in the kernel are weighted equally during the averaging, though they are not equidistant from the central **Cell**.

% Auto generated parameter table will be inserted here

## Example Pipelines

+ MassifPipeline
+ (05) SmallIN100 Crystallographic Statistics
+ (04) Small IN100 Crystallographic Statistics
+ EBSD_File_Processing/aptr12_Analysis
+ EBSD_File_Processing/avtr12_Analysis

## License & Copyright

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading