Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b1d6f47
BUG: Correct anisotropic surface-area weights
jmarquisbq Oct 15, 2026
971aa89
BUG: Reject mismatched surface-metric geometry and label sizes
jmarquisbq Oct 15, 2026
945f1a3
BUG: Improve surface-area accumulation precision
jmarquisbq Oct 15, 2026
df83795
BUG: Correct sphericity exponents
jmarquisbq Oct 15, 2026
697414c
DOC: Correct surface-metric interface and volume rules
jmarquisbq Oct 15, 2026
c7f1a50
BUG: Reject unsupported Feature Id array kinds in preflight
jmarquisbq Oct 15, 2026
1539428
REV: Share cell tuple-count validation
jmarquisbq Oct 15, 2026
29da66a
BUG: Clarify surface metric preflight errors
jmarquisbq Oct 15, 2026
14f3e78
REV: Clean up surface metric algorithm dependencies and reads
jmarquisbq Oct 15, 2026
a855ee3
PERF: Release the ratio buffer before computing sphericity
jmarquisbq Oct 15, 2026
d7d7f12
DOC: Explain voxel surface metrics with verified Small IN100 figures
jmarquisbq Oct 15, 2026
891e236
DOC: Use Viridis and enlarge the surface metric comparison
jmarquisbq Oct 15, 2026
f659a42
DOC: Explain temporary surface-metric type checks
jmarquisbq Oct 19, 2026
7f923ff
DOC: Put the sphericity figure caption in visible text
jmarquisbq Oct 19, 2026
2d3a195
DOC: Clarify nonfinite surface-metric results
jmarquisbq Oct 19, 2026
ff30052
DOC: Explain responsibility for image label ordering
jmarquisbq Oct 19, 2026
6c7ebbb
REV: Limit pi-root calculation to sphericity
jmarquisbq Oct 19, 2026
3b710ca
REV: Keep surface-metric feature counts in usize
jmarquisbq Oct 19, 2026
80960e7
REV: Use a const FeatureIds store in Scanline
jmarquisbq Oct 19, 2026
3c77f6f
TEST: Make the surface-metric fixture mode explicit
jmarquisbq Oct 19, 2026
6538fff
DOC: Explain the legacy sphericity exemplar tolerance
jmarquisbq Oct 19, 2026
87c4f9c
REV: Bound surface metric transfer buffers
jmarquisbq Oct 19, 2026
7f2c0f3
REV: Apply surface metric coding standards
jmarquisbq Oct 19, 2026
232e708
REV: Reuse cell tuple validation in three filters
jmarquisbq Oct 15, 2026
697a0a3
DOC: Define the shared tuple diagnostic prefix policy
jmarquisbq Oct 19, 2026
a1f160e
REV: Include the span type used by partition tests
jmarquisbq Oct 19, 2026
5d8ef6b
REV: Give vertex tuple mismatches a distinct diagnostic
jmarquisbq Oct 19, 2026
dc54103
REV: Guard concrete array kinds in migrated filters
jmarquisbq Oct 19, 2026
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
68 changes: 57 additions & 11 deletions src/Plugins/SimplnxCore/docs/ComputeSurfaceAreaToVolumeFilter.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,78 @@ This filter also optionally calculates the [Sphericity](https://en.wikipedia.org

![Equation for Sphericity used in the filter](Images/Sphericity_Equation.png)

This **Filter** determines whether a **Feature** touches an outer *Surface* of the sample volume. A **Feature** is considered touching the *Surface* of the sample if either of the following conditions are met:

+ Any cell location is x<sub>min</sub>, x<sub>max</sub>, y<sub>min</sub>, y<sub>max</sub>, z<sub>min</sub> or z<sub>max</sub>
+ Any cell has **Feature ID = 0** as a neighbor.
Use [Compute Surface Features](ComputeSurfaceFeaturesFilter.md) when you need a separate flag that identifies features touching the sample surface.

### Required Input Sources

- **Cell Feature Ids** -- the per-**Cell** **Feature** label array, typically produced by [Segment Features (Scalar)](ScalarSegmentFeaturesFilter.md) or another segmentation filter.
- **Number of Cells** -- the per-feature cell counts, typically produced by [Compute Feature Sizes](ComputeFeatureSizesFilter.md).

The label array must have one tuple per cell in the selected geometry. The array can be stored separately from that geometry. Its tuple count, cell ordering, and feature labels must describe the selected image. You are responsible for checking that the cell ordering and feature labels match the selected image. The tuple-count check cannot verify this correspondence. Each Feature Id must index a tuple in the selected feature data; the filter checks these index bounds.

## Algorithm

For each cell with a positive Feature Id, the filter examines its six face-sharing neighbors within the image. A face contributes area to the current feature when the neighbor has a different Feature Id, including Feature Id 0. An interface between two positive features contributes to each feature's area. Faces outside the image are omitted. Feature Id 0 is the background; its output tuple remains zero.

For cell spacing `(dx, dy, dz)`, the area of a face uses the two spacing components perpendicular to its normal:

- X-normal face: `dy * dz`.
- Y-normal face: `dx * dz`.
- Z-normal face: `dx * dy`.

![Fig. 1: Generated schematic showing all six voxel faces and the two spacing components used for each face area.](Images/ComputeSurfaceAreaToVolume_VoxelFaceAreas.png)

The filter calculates each feature's volume as `V = Number of Cells * dx * dy * dz`. It uses the supplied cell count without recounting the labels or checking that the count matches them. The surface-area-to-volume ratio is `S / V`, where `S` is the accumulated face area. Area has units of length squared, and volume has units of length cubed.

When *Calculate Sphericity* is enabled, the filter also calculates `Psi = pi^(1/3) * (6 * V)^(2/3) / S`. Psi is dimensionless. A mathematical sphere with a complete closed surface and consistent positive volume has sphericity 1. For a voxelized sphere with a complete counted surface and consistent positive volume, the stair-stepped surface has more area than an equal-volume smooth sphere, so its sphericity is below 1. Both output arrays use 32-bit floating-point values; face areas, accumulated areas, and metric calculations use 64-bit floating-point values.

### Algorithm selection

The filter automatically uses *Direct* when Cell Feature Ids are stored in memory and *Scanline* when they use out-of-core storage. Both methods use the same face-counting and volume rules.

### Direct

Direct reads neighboring labels from the array and accumulates one surface area per feature. Its additional working memory scales as `O(F)`, where `F` is the number of feature tuples, including background.

## Algorithm Details
### Scanline

- First, all the boundary **Cells** are found for each **Feature** (see also [Compute Boundary Cells (Image)](ComputeBoundaryCellsFilter.md)).
- Next, the surface area for each face that is in contact with a different **Feature** is totalled as long as that neighboring *featureId* is > 0.
- This number is divided by the volume of each **Feature**, calculated by taking the number of **Cells** of each **Feature** and multiplying by the volume of a **Cell**.
Scanline reads labels in sequential slices and keeps three adjacent XY slices in memory. It releases these slices before reading feature counts and writing metrics in bounded batches. Each batch has at most `min(65536, max(1, floor(F / 2)))` tuples, where `F` includes background. The count and result buffers together use at most 512 KiB. This is an implementation memory budget, not a limit on the number of features.

The 64-bit area accumulator still uses eight bytes per feature tuple. Additional working memory scales as `O(X * Y + F)`, where `X` and `Y` are image dimensions in cells. Scanline avoids buffering the full label volume, but the area accumulator can still be large when the feature count approaches the cell count. These memory estimates exclude the input/output stores, their caches, and allocator overhead.

A bulk read or write error stops execution. If a feature-count read or metric write fails after earlier batches completed, those earlier outputs remain written. Output updates are not transactional.

### Compatibility with earlier results

Corrected X/Y face weights can change results when `dx` differs from `dy`. The face-weight correction does not change the measured area when `dx = dy`, including when `dz` differs. Changes to numerical precision and the sphericity exponents can still change results, including isotropic results.

### Small IN100 comparison

The generated views below use segmented Small IN100 feature labels in a separate demonstration copy. The original spacing is `(0.25, 0.25, 0.25)` micrometers. The demonstration changes the spacing to `(0.25, 0.50, 0.25)` micrometers so that X-normal and Y-normal faces have different areas. The original dataset is unchanged, and the labels are reused without resampling. Both calculations use identical labels, cell counts derived from those labels, and demonstration spacing.

The earlier Direct implementation and the current filter each calculate sphericity over the complete three-dimensional volume. The views display those three-dimensional feature values on the same central XY slice, at zero-based Z index 58. Both views use the same dimensionless 0–1 Viridis color scale and physical aspect ratio. The comparison includes corrections to numerical precision and sphericity exponents as well as the X/Y face weights. Features cut by the image boundary can have incomplete counted surfaces, as described below.

![Small IN100 sphericity before and after the correction](Images/ComputeSurfaceAreaToVolume_SmallIN100_Sphericity.png)

Fig. 2: Generated before-and-after views of full-volume Small IN100 feature sphericity on a central XY slice. Spacing was altered from 0.25/0.25/0.25 to 0.25/0.50/0.25 micrometers for demonstration; both panels share the 0–1 Viridis color scale and physical aspect ratio.

### WARNING - Aliasing

The surface area will be the surface area of the **Cells** in contact with the neighboring **Feature** and will be influenced by the *aliasing* of the structure — the jagged, stair-stepped approximation of a smooth surface that results from representing it on a discrete voxel grid. As a result, the surface area to volume will likely be over-estimated with respect to the *real* **Feature**.

### WARNING - Skewed Results for features touching the surface
### WARNING - Incomplete surfaces and nonfinite results

Because the filter does not include any surface that is touching/connected to a "FeatureId = 0", those features that are in contact with the edge of the virtual volume or in contact with internal features that are labeled as "FeatureId = 0" will have their values skewed.
Image-exterior faces are omitted, so a feature touching the image boundary can have an incomplete measured surface. This can reduce its surface-area-to-volume ratio and increase its sphericity, even above 1. In-image faces against Feature Id 0 are included.

The filter does not reject zero or negative supplied cell counts or replace nonfinite results. For positive area and zero volume, the ratio is infinite and sphericity is zero. For positive volume and zero measured area, the ratio is zero and sphericity is infinite. Zero area with zero volume produces NaN (not a number). A negative volume can produce a negative ratio and NaN sphericity.

Zero or negative supplied counts do not give a positive feature volume. Check **Number of Cells** against the feature labels before interpreting either metric. A zero measured area does not support a finite sphericity value, but it can result from omitted image-exterior faces even when the labels and counts are correct.

### Warning - 2D Image Geometry Results

Because even a single slice has *volume* according to DREAM3D-NX, results will still be computed. These results should **NOT** be interpreted as "Boundary Length to Area" values.
For a single XY slice, each cell still has thickness `dz`, and the filter uses three-dimensional cell volumes. Both Z-normal faces lie outside the image and are omitted. The counted side-face area equals the counted in-plane boundary length times `dz`.

When the supplied counts match the labels, thickness cancels in the ratio. The result then equals counted in-plane boundary length divided by feature area, with units of inverse length. Image-exterior edges remain omitted, so this need not be the feature's full perimeter-to-area ratio. Optional sphericity still uses the three-dimensional formula and depends on the slice thickness; it is not a two-dimensional circularity measure.

% Auto generated parameter table will be inserted here

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