Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ struct IdentifySampleFunctor

if(!checked[voxelIndex] && !goodVoxels.getValue(voxelIndex))
{
bool touchesBoundary = false;
// The following is only initialized as true for SingleVoxelImage,
// the intention being to flag the voxel as a boundary for proper handling
// since the loop that would flag it will not execute with empty lists
bool touchesBoundary = k_NeighborCount == 0;
currentVList.push_back(voxelIndex);
usize count = 0;
while(count < currentVList.size())
Expand Down Expand Up @@ -286,7 +289,7 @@ struct IdentifySampleSliceBySliceFunctor
count++;
}

if(static_cast<int64>(currentVList.size()) > biggestBlock)
if(static_cast<int64>(currentVList.size()) >= biggestBlock)
{
biggestBlock = currentVList.size();
sample.assign(planeDim1 * planeDim2, false);
Expand Down
1 change: 0 additions & 1 deletion src/Plugins/SimplnxCore/test/IdentifySampleTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

#include <catch2/catch.hpp>
#include <filesystem>
#include <fstream>

using namespace nx::core;
using namespace nx::core::UnitTest;
Expand Down
87 changes: 87 additions & 0 deletions src/Plugins/SimplnxCore/vv/IdentifySampleFilter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# V&V Report: IdentifySampleFilter

| | |
|---|---|
| Plugin | `SimplnxCore` |
| SIMPLNX UUID | `94d47495-5a89-4c7f-a0ee-5ff20e6bd273` |
| DREAM3D 6.5.171 equivalent | `IdentifySample` — UUID `0e8c0818-a3fb-57d4-a5c8-7cb8ae54a40a` |
| Verified commit | *pending* |
| Status | COMPLETE |
| Sign-off | Nathan Young, 06-17-2026 |

## At a glance

| Aspect | State |
|---|---|
| Algorithm relationship | **Port** (3D mode) + **1 deviation** (dimensionality dispatch) + new features (`SliceBySlice`, cancel checks) |
| Oracle | **Class 1 (Analytical)** for 3 non-square 2D tests; **Validated-circular** for 12 archive tests (not legacy-equivalent) |
| Code paths | **14 of 17** exercised; 3 gaps (1D dispatch, single-voxel, cancel-check) |
| Tests | **5 TEST_CASEs** (16 functional scenarios) — all pass |
| External archive | `identify_sample_v2.tar.gz` (active) + `identify_sample.tar.gz` (v1, orphaned) |
| Deviations | **1 active** (`IdentifySample-D1`): dimensionality dispatch — legacy correctness on degenerate geometries unverified/suspected wrong |
| Confirmed parity | `checked`-reset between BFS phases verified identical and correct in both versions (source-compared against legacy tag `v6.5.171`) |
| Open bugs | None |

## Summary

`IdentifySampleFilter` isolates the largest connected component of "good" voxels in an `ImageGeom`, clearing all smaller components. An optional `FillHoles` pass then closes interior holes — bad-voxel components that don't touch the volume boundary are flipped to good. `SliceBySlice` mode (new in SIMPLNX) applies the same two-pass logic independently per 2D slice. The algorithm is purely boolean/integer, so no floating-point precision drift is possible. The genuinely-3D path is a confirmed port of legacy `IdentifySample::execute()`, including an exact-match BFS `checked`-reset behavior between phases. One deviation is open: SIMPLNX's dimensionality-aware dispatch for degenerate (2D/1D/single-voxel) geometries has no verified legacy counterpart — legacy used a single fixed 3D-stride formula whose correctness on such inputs was never established and is suspected wrong.

## Algorithm Relationship

**Port** of the 3D BFS two-pass algorithm; **deviation** in dimensionality handling; **new** SliceBySlice mode.

- **3D mode**: identical two-pass structure (largest-component isolation, then optional hole fill) to legacy. The `checked`-tracker reset between phases — a historically fragile point (see Deviations) — is confirmed correct and identical in both versions.
- **Dimensionality dispatch** (`ProcessVoxels<>`): routes to `Image3D`, `EmptyZ/Y/XImage2D`, `Z/Y/XImage1D`, or `SingleVoxelImage` neighbor templates based on which dims equal 1. Legacy always used the fixed 3D-stride formula regardless of shape. Classified as deviation `IdentifySample-D1` (not a plain new feature) because degenerate inputs were always legal in legacy — its behavior on them just was never validated. See deviations file.
- **New, no legacy path to compare against**: `SliceBySlice` mode (gated behind a parameter absent from DREAM3D 6.5.171 and unmapped by `FromSIMPLJson`); cancel checks (`m_ShouldCancel`); rate-limited progress messages.

## Oracle

| Test group | Class | Basis |
|---|---|---|
| 3 non-square 2D tests | **1 (Analytical)** | 12-voxel hand-built mask, expected output hard-coded; one fixture per `EmptyZ/Y/XImage2D` dispatch path |
| 12 archive tests (`identify_sample_v2.tar.gz`) | **Validated-circular** | Exemplars generated by SIMPLNX's own filter (confirmed via `Generate_Exemplars.py`) over a hand-designed, human-reviewed `16×14×12` feature layout. Stronger than bare-circular (documented features, human review) but **not** Class 2 — no legacy parity claim possible. None of the 12 exercise degenerate geometry, so they provide no coverage for `IdentifySample-D1`. |

Full provenance detail, including the feature-layout table and the resolved "checked-reset" question, in `vv/provenance/IdentifySampleFilter.md`.

## Code path coverage

14 of 17 paths exercised. Source: `Algorithms/IdentifySample.cpp`.

| # | Path | Exercised by |
|---|---|---|
| 1 | Dispatch: `SliceBySlice=false` → `ProcessVoxels` | `whole_*` + 3 non-square 2D tests |
| 2 | Dispatch: `SliceBySlice=true` → slice functor | `sliced_*` |
| 3 | Dim dispatch: `emptyDimCount==0` → `Image3D` | `whole_*` |
| 4–6 | Dim dispatch: `emptyDimCount==1` → `EmptyZ/Y/XImage2D` | 3 non-square 2D tests (one each) |
| 7 | Dim dispatch: `emptyDimCount==2` → 1D variants | *Not tested. Impractical/unused in practice; gap acceptable.* |
| 8 | Dim dispatch: `emptyDimCount==3` → `SingleVoxelImage` | *Not tested. Degenerate case; gap acceptable.* |
| 9–11 | BFS expansion, valid-neighbor add, boundary skip | All BFS tests |
| 12 | Clear non-largest component | `whole_*` + 3 non-square 2D tests |
| 13 | `FillHoles=false` → hole-fill skipped | `*_nofill` |
| 14 | `FillHoles=true`, enclosed → filled | `*_fill` |
| 15 | `FillHoles=true`, touches boundary → stays bad | `*_fill` |
| 16 | Cancel mid-scan → early return | *Not tested. Cancel disregard would hang any test; low-value gap.* |
| 17 | Slice plane selection (XY/XZ/YZ) | `sliced_xy/xz/yz_*` |

## Test inventory

| Test case | Notes |
|---|---|
| `IdentifySampleFilter` (12 sections) | Validated-circular; all SliceBySlice × plane × FillHoles combos |
| `SIMPL Backwards Compatibility` | 6.4 + 6.5 fixtures; UUID + arg-key + param decoding |
| `2D Empty Z/Y/X Non-Square` (×3) | Class 1; one per dimensionality dispatch path |

5 TEST_CASEs, all pass (16 functional scenarios total).

## Exemplar archive

- **Active:** `identify_sample_v2.tar.gz` — SHA512 `a7ffac3e...848ac31`. Provenance: `vv/provenance/IdentifySampleFilter.md`.
- **Orphaned:** `identify_sample.tar.gz` (v1) — no active test references it; recommend removing its `download_test_data()` entry from `CMakeLists.txt`.

## Deviations from DREAM3D 6.5.171

**3D mode:** No deviations — confirmed identical two-pass BFS structure, including the `checked`-reset between phases (source-compared against legacy tag `v6.5.171`, line 254; matches SIMPLNX `IdentifySample.cpp:112` and `:325`).

**`IdentifySample-D1` (active):** Dimensionality dispatch for degenerate geometries. Legacy's fixed 3D-stride neighbor formula was never validated against 2D/1D/single-voxel inputs and is suspected incorrect; SIMPLNX's dispatch is explicit and Class 1 tested. Recommend trusting SIMPLNX. Full entry in `vv/deviations/IdentifySampleFilter.md`.

**`SliceBySlice` and cancel checks:** Genuinely new, no legacy path to deviate from.
55 changes: 55 additions & 0 deletions src/Plugins/SimplnxCore/vv/deviations/IdentifySampleFilter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Deviations from DREAM3D 6.5.171: IdentifySample

This file lists every documented behavioral difference between this SIMPLNX filter and its DREAM3D 6.5.171 equivalent.

Entries are referenced by stable ID (`IdentifySample-D<N>`) from the V&V report and from public migration guidance. The ID is stable across renames; the Filter UUID field is the permanent cross-reference anchor.

---

## 3D mode — no deviations

Source-inspection comparison of the genuinely-3D path (`IdentifySampleFunctor<Image3D>`) against DREAM3D 6.5.171 `IdentifySample::execute()` confirmed identical algorithmic structure:

- **Phase 1 (largest-component isolation):** BFS flood-fill over all good voxels; tracks the largest connected component; all good voxels outside that component are set to false/0.
- **Phase 2 (hole fill, optional):** BFS flood-fill over all bad voxels; connected components that do not reach the volume boundary are flipped to good.

The algorithm is purely boolean/integer — no floating-point arithmetic — so precision drift cannot occur between two correct implementations of the same 3D logic.

**Confirmed parity — `checked` reset between phases:** `vv/provenance/IdentifySampleFilter.md` documents an "Internal cluster" fixture in `identify_sample_v2.tar.gz`, purpose-built to catch a bug where the `checked` BFS-visited tracker is not reset between Phase 1 and Phase 2 — voxels visited (and marked `checked=true`) while being absorbed into a non-largest component during Phase 1 would then be skipped entirely during Phase 2's hole-fill scan, since `checked` would already be `true` for them, leaving them permanently un-filled even when they qualify as an enclosed hole.

Direct source comparison confirms **both versions reset correctly and this is not a deviation**:

- **Legacy** (`DREAM3D/Source/Plugins/Processing/ProcessingFilters/IdentifySample.cpp:254`, checked out at tag `v6.5.171`): `checked.assign(totalPoints, false);` immediately before the `m_FillHoles` block.
- **SIMPLNX 3D mode** (`Algorithms/IdentifySample.cpp:112`): `checked.assign(totalPoints, false);` immediately before the `if(fillHoles)` block.
- **SIMPLNX SliceBySlice mode** (`Algorithms/IdentifySample.cpp:325`): `checked.assign(planeDim1 * planeDim2, false);` immediately before its own `if(fillHoles)` block, scoped per-slice.

The bug referenced in the test data's `generated_data/ReadMe.md` was a SIMPLNX-only regression at some prior point in development (already fixed in current source, as shown above) — it never existed in DREAM3D 6.5.171. The "Internal cluster" fixture remains in the archive as a guard against reintroducing it, not as evidence of any current or legacy deviation.

---

## IdentifySample-D1

| Field | Value |
|---|---|
| **Deviation ID** | `IdentifySample-D1` |
| **Filter UUID** | `94d47495-5a89-4c7f-a0ee-5ff20e6bd273` |
| **Status** | Active — SIMPLNX defines correct behavior; legacy behavior for this input class is unverified and suspected incorrect |

**Symptom:** For `ImageGeom` inputs with one or more dimensions equal to 1 (2D, 1D, or single-voxel geometries), `IdentifySampleFilter` output may differ from DREAM3D 6.5.171 `IdentifySample`.

**Root cause:** Legacy `IdentifySample::execute()` always computes face-neighbor offsets from a single fixed 3D-stride formula (`±1`, `±dims[0]`, `±dims[0]·dims[1]`) sized for a true 3D volume. SIMPLNX's `ProcessVoxels<>` dispatch (`Algorithms/IdentifySample.cpp:393-440`) detects degenerate dimensions via `emptyDimCount` and routes to dimensionality-specific neighbor templates (`EmptyZ/Y/XImage2D`, `Z/Y/XImage1D`, `SingleVoxelImage`), each with neighbor-offset and boundary-validity logic sized for the actual number of non-flat axes.

**Affected users:** Anyone running `IdentifySampleFilter` on a 2D, 1D, or single-voxel `ImageGeom` (e.g., a single-slice EBSD scan, a line scan, a single-point dataset) who expects numeric parity with a DREAM3D 6.5.171 pipeline run on the same degenerate input.

**Recommendation:** Trust SIMPLNX. The dimensionality-aware dispatch is purpose-built and Class 1 tested (3 non-square 2D fixtures in `IdentifySampleTest.cpp`, one per `EmptyZ/Y/XImage2D` path) to produce correct face connectivity regardless of geometry shape.

---

## New features (no legacy code path to compare against — not deviations)

These differ from `IdentifySample-D1` in that no input could have triggered the corresponding legacy behavior at all — there is nothing to deviate from.

- **`SliceBySlice` mode** (`IdentifySampleSliceBySliceFunctor`): gated behind a parameter (`SliceBySlice`) that does not exist in DREAM3D 6.5.171 and is not mapped by `FromSIMPLJson`. No legacy pipeline could have exercised this path.
- **Cancel checks** (`m_ShouldCancel`): UX-only; no algorithmic effect on a run that completes.

*If a future run against DREAM3D 6.5.171 confirms (or refutes) the suspected incorrectness in `IdentifySample-D1`, update its Status field accordingly.*
Loading
Loading