Skip to content

BUG: Remove/Extract Flagged Features hangs when Fill-in Removed Features is enabled #1698

Description

@imikejackson

Summary

Remove/Extract Flagged Features hangs indefinitely when Fill-in Removed Features is enabled and
any vacated cell fails to acquire a fill source. There is no error and no progress — the dilation
loop spins forever and the pipeline must be killed.

Root cause

IdentifyNeighbors() in src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/RemoveFlaggedFeatures.cpp
tallies the most common feature among a bad cell's six face neighbors, but only records a fill source
inside the found branch (line 97):

bool found = false;
for(usize featIndex = 0; featIndex < discoveredFeatures.size(); featIndex++)
{
  if(discoveredFeatures[featIndex] == feature)
  {
    found = true;
    numHits[featIndex]++;
    current = numHits[featIndex];
    if(current > most)
    {
      most = current;
      storageArray[voxelIndex] = static_cast<int32>(neighborPoint);   // line 97
    }
    break;
  }
}
if(!found)
{
  discoveredFeatures.push_back(feature);   // line 104: no numHits increment, no source recorded
}

On the first sighting of a feature the entry is pushed to discoveredFeatures but numHits is
never incremented, so it stays 0. A source is therefore only ever recorded on the second or
later
sighting of the same feature.

Consequently a bad cell whose valid face neighbors all belong to distinct features, or which has
only a single valid neighbor, never receives a storageArray entry. FindVoxelArrays() copies
nothing into it, so it remains at -1. The next pass sees featureName <= 0, sets
shouldLoop = true again, and the do { ... } while(shouldLoop) loop in RemoveFlaggedFeatures::operator()
never terminates.

Reproduction

A 5x2x1 ImageGeom, FeatureIds = 1 1 1 2 3 / 1 4 4 4 3, feature sizes 4/1/2/3. Remove features 2
and 3 with Fill-in Removed Features enabled. FeatureIds becomes 1 1 1 -1 -1 / 1 4 4 4 -1 and
none of the three vacated cells can be filled:

Cell Valid neighbors Source recorded?
3 features {1, 4} — both first sightings no
4 both neighbors are -1 no
9 feature {4} — single sighting no

The filter hangs.

Why this was never caught

The fill path has no execution test coverage. RemoveFlaggedFeaturesTest.cpp passes
FillRemovedFeatures = false at both of its execute sites (lines 144 and 218); line 279 is only a
SIMPL-conversion argument assertion and never runs the algorithm.

On large 3D volumes a bad cell almost always has two or more face neighbors belonging to the same
feature, which satisfies the second-sighting condition and lets the loop terminate. The defect
surfaces on thin geometries (single-slice or single-voxel-deep volumes) and on small or isolated bad
regions.

Proposed fix

Count the first sighting as a hit, which also makes numHits a true tally rather than a count of
repeat sightings:

if(!found)
{
  discoveredFeatures.push_back(feature);
  numHits[discoveredFeatures.size() - 1] = 1;
  if(1 > most)
  {
    most = 1;
    storageArray[voxelIndex] = static_cast<int32>(neighborPoint);
  }
}

Any cell with at least one valid neighbor then acquires a source. Cells with no valid neighbor on the
first pass are filled on a later pass once their neighbors are resolved, so the loop terminates as
long as at least one feature survives — which FlagFeatures() already guarantees by erroring when
every feature is flagged.

This changes behavior: previously such cells were left unfilled and the filter never returned; now
they are filled from the first-seen neighboring feature, ties going to the first encountered.

Requested work

Beyond the fix, this filter should have the entire V&V suite performed:

  • Oracle classification and independent expected output
  • SIMPLNX vs. oracle reconciliation
  • Comparison against legacy DREAM3D 6.5.171, written up as structured deviation entries
  • Full test-coverage inventory, with every enumerated code path mapped to a named test

The fill-by-dilation path in particular needs real assertions on which surviving feature each
vacated cell is assigned to, not merely that no cell is left at zero. An infinite loop reachable from
a checkbox in the GUI, in a code path with no execution coverage, is exactly the class of defect the
V&V process exists to surface.

For context, the neighboring filters in this family — FillBadData and
ReplaceElementAttributesWithNeighborValues — are already V&V'ed;
Remove/Extract Flagged Features is not.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions