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
8 changes: 4 additions & 4 deletions tests/test_all.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1012,14 +1012,14 @@ TEST(TEST_NYXUS, TEST_SHAPE2D_CONTOUR_FEATURES)
ASSERT_NO_THROW(test_shape2d_contour_features());
}

TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_CONTOUR_DIAMETER_EQUAL_PERIMETER)
TEST(TEST_NYXUS, TEST_SHAPE2D_CONVEX_HULL_FEATURES)
{
ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_contour_diameter_equal_perimeter());
ASSERT_NO_THROW(test_shape2d_convex_hull_features());
}

TEST(TEST_NYXUS, TEST_SHAPE2D_CONVEX_HULL_FEATURES)
TEST(TEST_NYXUS, TEST_SHAPE2D_SKIMAGE_ORIENTATION_AND_EROSIONS)
{
ASSERT_NO_THROW(test_shape2d_convex_hull_features());
ASSERT_NO_THROW(test_shape2d_skimage_orientation_and_erosions());
}

TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_EXTREMA_FEATURES)
Expand Down
23 changes: 14 additions & 9 deletions tests/test_morphology_regression.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ void test_shape2d_ellipse_features()
assert_unvetted_no_direct_oracle_shape2d_feature(fvals, Nyxus::Feature2D::MINOR_AXIS_LENGTH, "MINOR_AXIS_LENGTH");
assert_unvetted_no_direct_oracle_shape2d_feature(fvals, Nyxus::Feature2D::ELONGATION, "ELONGATION");
assert_unvetted_no_direct_oracle_shape2d_feature(fvals, Nyxus::Feature2D::ECCENTRICITY, "ECCENTRICITY");
assert_unvetted_no_direct_oracle_shape2d_feature(fvals, Nyxus::Feature2D::ORIENTATION, "ORIENTATION");
// ORIENTATION is vetted vs scikit-image in test_morphology_skimage.h; ROUNDNESS is vetted by
// documented-formula conformance in test_shape2d_documented_formula_conformance_no_external_oracle.
assert_unvetted_no_direct_oracle_shape2d_feature(fvals, Nyxus::Feature2D::ROUNDNESS, "ROUNDNESS");
}

Expand Down Expand Up @@ -85,6 +86,12 @@ void test_shape2d_documented_formula_conformance_no_external_oracle()
const double round_formula = 4.0 * A / (PI * major * major);
ASSERT_NEAR(fvals[static_cast<int>(Nyxus::Feature2D::ROUNDNESS)][0], round_formula, 1e-9)
<< "ROUNDNESS does not match 4A/(pi*major^2)";

// DIAMETER_EQUAL_PERIMETER = P / pi (contour.cpp) -- diameter of the circle with the same
// perimeter. Pure double arithmetic on the vetted PERIMETER, so it conforms exactly.
const double dep_formula = P / PI;
ASSERT_NEAR(fvals[static_cast<int>(Nyxus::Feature2D::DIAMETER_EQUAL_PERIMETER)][0], dep_formula, 1e-9)
<< "DIAMETER_EQUAL_PERIMETER does not match PERIMETER/pi";
}

void test_shape2d_unvetted_no_direct_oracle_radius_features()
Expand All @@ -97,13 +104,8 @@ void test_shape2d_unvetted_no_direct_oracle_radius_features()
assert_unvetted_no_direct_oracle_shape2d_feature(fvals, Nyxus::Feature2D::ROI_RADIUS_MEDIAN, "ROI_RADIUS_MEDIAN");
}

void test_shape2d_verifiable_with_3p_builtin_oracle_contour_diameter_equal_perimeter()
{
std::vector<std::vector<double>> fvals;
calculate_shape2d_feature_values(fvals);

assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::DIAMETER_EQUAL_PERIMETER, "DIAMETER_EQUAL_PERIMETER");
}
// DIAMETER_EQUAL_PERIMETER is now vetted by documented-formula conformance (P/pi) in
// test_shape2d_documented_formula_conformance_no_external_oracle.

void test_shape2d_verifiable_with_3p_builtin_oracle_fractal_circle_features()
{
Expand All @@ -120,9 +122,12 @@ void test_shape2d_verifiable_with_3p_builtin_oracle_geodetic_thickness_erosion_f
{
std::vector<std::vector<double>> fvals;
calculate_shape2d_feature_values(fvals);
// GEODETIC_LENGTH stays regression: geo_len_thickness.cpp truncates PERIMETER to size_t and uses
// integer division, so its value (10.0) deviates ~11% from the real-valued rectangle formula
// (~11.13); vetting it analytically would bake in the truncation. THICKNESS is vetted vs imea.
assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::GEODETIC_LENGTH, "GEODETIC_LENGTH");
assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::THICKNESS, "THICKNESS");
assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EROSIONS_2_VANISH, "EROSIONS_2_VANISH");
// EROSIONS_2_VANISH is now vetted vs scikit-image (square(3)) in test_morphology_skimage.h.
}

// ---------------------------------------------------------------------------------------------------
Expand Down
19 changes: 19 additions & 0 deletions tests/test_morphology_skimage.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,22 @@ void test_shape2d_convex_hull_features()
assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::CONVEX_HULL_AREA, "CONVEX_HULL_AREA", 100.0);
assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::SOLIDITY, "SOLIDITY", 100.0);
}

// ORIENTATION and EROSIONS_2_VANISH vetted vs scikit-image (tests/vetting/oracles/gen_morphology_skimage.py).
// ORIENTATION: skimage regionprops orientation is measured from the row axis; Nyxus measures the same
// ellipse's major axis from the x axis, so NYXUS == 90 - degrees(skimage.orientation) = 70.4173944984
// (matches to 10 decimals -- the angle is invariant to the pixel-size second-moment correction that makes
// the AXIS LENGTHS differ ~1.4%, which is why MAJOR/MINOR/ECCENTRICITY stay regression).
// EROSIONS_2_VANISH: Nyxus' 3x3 (8-connected) structuring element == skimage square(3); the count (1)
// matches, and disk(1)/4-connected gives 2, so the test also pins the connectivity convention.
void test_shape2d_skimage_orientation_and_erosions()
{
std::vector<std::vector<double>> fvals;
calculate_shape2d_feature_values(fvals);

// skimage-derived goldens (90 - degrees(regionprops.orientation); square(3) erosion count)
ASSERT_NEAR(fvals[static_cast<int>(Nyxus::Feature2D::ORIENTATION)][0], 70.4173944984207, 1e-3)
<< "ORIENTATION does not match 90 - skimage.orientation(deg)";
ASSERT_NEAR(fvals[static_cast<int>(Nyxus::Feature2D::EROSIONS_2_VANISH)][0], 1.0, 1e-9)
<< "EROSIONS_2_VANISH does not match skimage square(3) erosion count";
}
6 changes: 3 additions & 3 deletions tests/vetting/coverage_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

_Generated by check_coverage.py from oracle_coverage.csv. Do not edit by hand._

Features vetted by >=1 oracle: 604/758 (80%)
regression: 154 untested: 0
Features vetted by >=1 oracle: 607/758 (80%)
regression: 151 untested: 0

| family | total | vetted | regression | untested |
|---|---|---|---|---|
Expand All @@ -17,7 +17,7 @@ regression: 154 untested: 0
| imq | 6 | 0 | 6 | 0 |
| intensity_histogram | 47 | 47 | 0 | 0 |
| moments | 180 | 118 | 62 | 0 |
| morphology | 113 | 77 | 36 | 0 |
| morphology | 113 | 80 | 33 | 0 |
| neighbor | 9 | 2 | 7 | 0 |
| ngldm | 38 | 20 | 18 | 0 |
| ngtdm | 10 | 10 | 0 | 0 |
Expand Down
Loading
Loading