From c635aa9b3117bac027892cd587fe0cb201aaf276 Mon Sep 17 00:00:00 2001 From: Vasu Jaganath Date: Thu, 28 May 2026 20:53:13 -0400 Subject: [PATCH] feat: re-organize and create complete implementation unit test coverage for 492 2D features --- tests/test_2d_geometric_moments.h | 346 ++++++++++++++++++++++ tests/test_2d_remaining_features.h | 397 ++++++++++++++++++++++++++ tests/test_all.cc | 144 ++++++++-- tests/test_gabor.cc | 4 +- tests/test_gabor.h | 2 +- tests/test_ibsi_gldzm.h | 6 +- tests/test_ibsi_ngldm.h | 6 +- tests/test_neighbors_2d.h | 33 ++- tests/test_pixel_intensity_features.h | 44 +-- tests/test_shape_morphology_2d.h | 113 ++++++-- 10 files changed, 1010 insertions(+), 85 deletions(-) create mode 100644 tests/test_2d_geometric_moments.h create mode 100644 tests/test_2d_remaining_features.h diff --git a/tests/test_2d_geometric_moments.h b/tests/test_2d_geometric_moments.h new file mode 100644 index 00000000..f00c0f57 --- /dev/null +++ b/tests/test_2d_geometric_moments.h @@ -0,0 +1,346 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "../src/nyx/roi_cache.h" +#include "../src/nyx/features/2d_geomoments.h" +#include "../src/nyx/features/contour.h" +#include "test_main_nyxus.h" + +struct GeomomentExpectation +{ + Nyxus::Feature2D feature; + const char* name; + double expected; + bool unvetted_no_direct_oracle = false; +}; + +static GeomomentExpectation unvetted_no_direct_oracle_geomoment( + Nyxus::Feature2D feature, + const char* name, + double expected) +{ + return {feature, name, expected, true}; +} + +static Fsettings make_2d_geomoment_settings() +{ + Fsettings s; + s.resize(static_cast(NyxSetting::__COUNT__)); + s[static_cast(NyxSetting::SOFTNAN)].rval = 0.0; + s[static_cast(NyxSetting::TINY)].rval = 0.0; + s[static_cast(NyxSetting::SINGLEROI)].bval = false; + s[static_cast(NyxSetting::GREYDEPTH)].ival = 256; + s[static_cast(NyxSetting::PIXELSIZEUM)].rval = 1.0; + s[static_cast(NyxSetting::XYRES)].rval = 1.0; + s[static_cast(NyxSetting::PIXELDISTANCE)].ival = 1; + s[static_cast(NyxSetting::USEGPU)].bval = false; + s[static_cast(NyxSetting::VERBOSLVL)].ival = 0; + s[static_cast(NyxSetting::IBSI)].bval = false; + return s; +} + +static double geomoment_fixture_intensity(int x, int y) +{ + return 10.0 + 3.0 * x + 5.0 * y + static_cast((x * y) % 7); +} + +static void load_geomoment_fixture(LR& roidata) +{ + constexpr int width = 48; + constexpr int height = 40; + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + const auto intensity = static_cast(geomoment_fixture_intensity(x, y)); + if (roidata.aux_area == 0) + init_label_record_3(roidata, x, y, intensity); + else + update_label_record_3(roidata, x, y, intensity); + } + } + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + const auto intensity = static_cast(geomoment_fixture_intensity(x, y)); + roidata.raw_pixels.push_back(Pixel2(x, y, intensity)); + } + } + + roidata.make_nonanisotropic_aabb(); + roidata.aux_image_matrix.allocate( + roidata.aabb.get_width(), + roidata.aabb.get_height()); + roidata.aux_image_matrix.calculate_from_pixelcloud(roidata.raw_pixels, roidata.aabb); +} + +static void calculate_2d_geomoment_feature_values(std::vector>& fvals) +{ + Fsettings s = make_2d_geomoment_settings(); + + LR roidata(1401); + load_geomoment_fixture(roidata); + roidata.initialize_fvals(); + + ContourFeature contour; + contour.calculate(roidata, s); + contour.save_value(roidata.fvals); + + Smoms2D_feature shape_moments; + shape_moments.calculate(roidata, s); + shape_moments.save_value(roidata.fvals); + + Imoms2D_feature intensity_moments; + intensity_moments.calculate(roidata, s); + intensity_moments.save_value(roidata.fvals); + + fvals = roidata.fvals; +} + +static void assert_2d_geomoment_features( + const std::vector>& fvals, + const std::vector& expectations) +{ + for (const auto& item : expectations) + { + const double actual = fvals[static_cast(item.feature)][0]; + const double scale = std::max({1.0, std::abs(item.expected), std::abs(actual)}); + const double tolerance = 1e-6 * scale; + const std::string review_name = item.unvetted_no_direct_oracle ? + std::string("UNVETTED_NO_DIRECT_ORACLE__") + item.name : + item.name; + SCOPED_TRACE(review_name); + ASSERT_TRUE(std::isfinite(actual)) << review_name << " returned a non-finite value"; + ASSERT_NEAR(actual, item.expected, tolerance) << review_name; + } +} + +static const std::vector shape_geomoment_expectations{ + {Nyxus::Feature2D::SPAT_MOMENT_00, "SPAT_MOMENT_00", 1920}, + {Nyxus::Feature2D::SPAT_MOMENT_01, "SPAT_MOMENT_01", 37440}, + {Nyxus::Feature2D::SPAT_MOMENT_02, "SPAT_MOMENT_02", 985920}, + {Nyxus::Feature2D::SPAT_MOMENT_03, "SPAT_MOMENT_03", 29203200}, + {Nyxus::Feature2D::SPAT_MOMENT_10, "SPAT_MOMENT_10", 45120}, + {Nyxus::Feature2D::SPAT_MOMENT_11, "SPAT_MOMENT_11", 879840}, + {Nyxus::Feature2D::SPAT_MOMENT_12, "SPAT_MOMENT_12", 23169120}, + {Nyxus::Feature2D::SPAT_MOMENT_13, "SPAT_MOMENT_13", 686275200}, + {Nyxus::Feature2D::SPAT_MOMENT_20, "SPAT_MOMENT_20", 1428800}, + {Nyxus::Feature2D::SPAT_MOMENT_21, "SPAT_MOMENT_21", 27861600}, + {Nyxus::Feature2D::SPAT_MOMENT_22, "SPAT_MOMENT_22", 733688800}, + {Nyxus::Feature2D::SPAT_MOMENT_23, "SPAT_MOMENT_23", 21732048000}, + {Nyxus::Feature2D::SPAT_MOMENT_30, "SPAT_MOMENT_30", 50895360}, + {Nyxus::Feature2D::CENTRAL_MOMENT_00, "CENTRAL_MOMENT_00", 1920}, + {Nyxus::Feature2D::CENTRAL_MOMENT_01, "CENTRAL_MOMENT_01", 960}, + {Nyxus::Feature2D::CENTRAL_MOMENT_02, "CENTRAL_MOMENT_02", 256320}, + {Nyxus::Feature2D::CENTRAL_MOMENT_03, "CENTRAL_MOMENT_03", 384000}, + {Nyxus::Feature2D::CENTRAL_MOMENT_10, "CENTRAL_MOMENT_10", 960}, + {Nyxus::Feature2D::CENTRAL_MOMENT_11, "CENTRAL_MOMENT_11", 480}, + {Nyxus::Feature2D::CENTRAL_MOMENT_12, "CENTRAL_MOMENT_12", 128160}, + {Nyxus::Feature2D::CENTRAL_MOMENT_13, "CENTRAL_MOMENT_13", 192000}, + {Nyxus::Feature2D::CENTRAL_MOMENT_20, "CENTRAL_MOMENT_20", 368960}, + {Nyxus::Feature2D::CENTRAL_MOMENT_21, "CENTRAL_MOMENT_21", 184480}, + {Nyxus::Feature2D::CENTRAL_MOMENT_22, "CENTRAL_MOMENT_22", 49256160}, + {Nyxus::Feature2D::CENTRAL_MOMENT_23, "CENTRAL_MOMENT_23", 73792000}, + {Nyxus::Feature2D::CENTRAL_MOMENT_30, "CENTRAL_MOMENT_30", 552960}, + {Nyxus::Feature2D::CENTRAL_MOMENT_31, "CENTRAL_MOMENT_31", 276480}, + {Nyxus::Feature2D::CENTRAL_MOMENT_32, "CENTRAL_MOMENT_32", 73820160}, + {Nyxus::Feature2D::CENTRAL_MOMENT_33, "CENTRAL_MOMENT_33", 110592000}, + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_00, "NORM_SPAT_MOMENT_00", 1), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_01, "NORM_SPAT_MOMENT_01", 0.44502457797294748), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_02, "NORM_SPAT_MOMENT_02", 0.26744791666666667), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_03, "NORM_SPAT_MOMENT_03", 0.18079123480150991), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_10, "NORM_SPAT_MOMENT_10", 0.53631167089047516), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_11, "NORM_SPAT_MOMENT_11", 0.23867187500000001), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_12, "NORM_SPAT_MOMENT_12", 0.14343543906367653), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_13, "NORM_SPAT_MOMENT_13", 0.096960449218749994), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_20, "NORM_SPAT_MOMENT_20", 0.38758680555555558), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_21, "NORM_SPAT_MOMENT_21", 0.17248565457024395), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_22, "NORM_SPAT_MOMENT_22", 0.10365928367332176), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_23, "NORM_SPAT_MOMENT_23", 0.070072297169161621), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_30, "NORM_SPAT_MOMENT_30", 0.31508310664815414), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_31, "NORM_SPAT_MOMENT_31", 0.14021972656250001), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_32, "NORM_SPAT_MOMENT_32", 0.084268320449909992), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::NORM_SPAT_MOMENT_33, "NORM_SPAT_MOMENT_33", 0.056964263916015626), + {Nyxus::Feature2D::NORM_CENTRAL_MOMENT_02, "NORM_CENTRAL_MOMENT_02", 0.069531250000000003}, + {Nyxus::Feature2D::NORM_CENTRAL_MOMENT_03, "NORM_CENTRAL_MOMENT_03", 0.0023772680447272832}, + {Nyxus::Feature2D::NORM_CENTRAL_MOMENT_11, "NORM_CENTRAL_MOMENT_11", 0.00013020833333333333}, + {Nyxus::Feature2D::NORM_CENTRAL_MOMENT_12, "NORM_CENTRAL_MOMENT_12", 0.00079341320992773077}, + {Nyxus::Feature2D::NORM_CENTRAL_MOMENT_20, "NORM_CENTRAL_MOMENT_20", 0.10008680555555556}, + {Nyxus::Feature2D::NORM_CENTRAL_MOMENT_21, "NORM_CENTRAL_MOMENT_21", 0.0011420791898210656}, + {Nyxus::Feature2D::NORM_CENTRAL_MOMENT_30, "NORM_CENTRAL_MOMENT_30", 0.0034232659844072879}, + {Nyxus::Feature2D::HU_M1, "HU_M1", 0.16961805555555556}, + {Nyxus::Feature2D::HU_M2, "HU_M2", 0.00093370979214891993}, + {Nyxus::Feature2D::HU_M3, "HU_M3", 2.1882410402651178e-06}, + {Nyxus::Feature2D::HU_M4, "HU_M4", 3.0166188385260932e-05}, + {Nyxus::Feature2D::HU_M5, "HU_M5", 4.598098572281346e-10}, + {Nyxus::Feature2D::HU_M6, "HU_M6", 0.0023774353872890023}, + {Nyxus::Feature2D::HU_M7, "HU_M7", -2.3604559630908652e-10}, +}; + +static const std::vector shape_weighted_geomoment_expectations{ + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_SPAT_MOMENT_00, "WEIGHTED_SPAT_MOMENT_00", 2498.7137745347236), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_SPAT_MOMENT_01, "WEIGHTED_SPAT_MOMENT_01", 56490.467057333364), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_SPAT_MOMENT_02, "WEIGHTED_SPAT_MOMENT_02", 1384474.7445020285), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_SPAT_MOMENT_03, "WEIGHTED_SPAT_MOMENT_03", 37605700.456672639), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_SPAT_MOMENT_10, "WEIGHTED_SPAT_MOMENT_10", 66428.864797854694), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_SPAT_MOMENT_11, "WEIGHTED_SPAT_MOMENT_11", 1505032.6106230586), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_SPAT_MOMENT_12, "WEIGHTED_SPAT_MOMENT_12", 37215299.240302473), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_SPAT_MOMENT_20, "WEIGHTED_SPAT_MOMENT_20", 1970501.3917437526), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_SPAT_MOMENT_21, "WEIGHTED_SPAT_MOMENT_21", 45088115.602599062), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_SPAT_MOMENT_30, "WEIGHTED_SPAT_MOMENT_30", 65035567.600335725), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_CENTRAL_MOMENT_02, "WEIGHTED_CENTRAL_MOMENT_02", 108271.66085414639), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_CENTRAL_MOMENT_03, "WEIGHTED_CENTRAL_MOMENT_03", 1648221.2155424568), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_CENTRAL_MOMENT_11, "WEIGHTED_CENTRAL_MOMENT_11", 4109.7206134559083), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_CENTRAL_MOMENT_12, "WEIGHTED_CENTRAL_MOMENT_12", 330371.75284171134), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_CENTRAL_MOMENT_20, "WEIGHTED_CENTRAL_MOMENT_20", 205330.93384081553), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_CENTRAL_MOMENT_21, "WEIGHTED_CENTRAL_MOMENT_21", 496695.03645982972), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_CENTRAL_MOMENT_30, "WEIGHTED_CENTRAL_MOMENT_30", 2136803.5531487665), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WT_NORM_CTR_MOM_02, "WT_NORM_CTR_MOM_02", 0.017341305008900215), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WT_NORM_CTR_MOM_03, "WT_NORM_CTR_MOM_03", 0.0052810979515541092), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WT_NORM_CTR_MOM_11, "WT_NORM_CTR_MOM_11", 0.00065823243217178482), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WT_NORM_CTR_MOM_12, "WT_NORM_CTR_MOM_12", 0.0010585506185281591), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WT_NORM_CTR_MOM_20, "WT_NORM_CTR_MOM_20", 0.032886780561097596), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WT_NORM_CTR_MOM_21, "WT_NORM_CTR_MOM_21", 0.0015914703165204656), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WT_NORM_CTR_MOM_30, "WT_NORM_CTR_MOM_30", 0.0068465742104244923), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_HU_M1, "WEIGHTED_HU_M1", 0.050228085569997812), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_HU_M2, "WEIGHTED_HU_M2", 0.00024339488988301761), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_HU_M3, "WEIGHTED_HU_M3", 1.3732402653252524e-05), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_HU_M4, "WEIGHTED_HU_M4", 0.00010972319316066924), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_HU_M5, "WEIGHTED_HU_M5", -4.0924793325555725e-09), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_HU_M6, "WEIGHTED_HU_M6", 0.0052813682812053835), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::WEIGHTED_HU_M7, "WEIGHTED_HU_M7", -3.2208361663964004e-09), +}; + +static const std::vector intensity_geomoment_expectations{ + {Nyxus::Feature2D::IMOM_RM_00, "IMOM_RM_00", 346635}, + {Nyxus::Feature2D::IMOM_RM_01, "IMOM_RM_01", 8040325}, + {Nyxus::Feature2D::IMOM_RM_02, "IMOM_RM_02", 227941125}, + {Nyxus::Feature2D::IMOM_RM_03, "IMOM_RM_03", 7040124229}, + {Nyxus::Feature2D::IMOM_RM_10, "IMOM_RM_10", 9253494}, + {Nyxus::Feature2D::IMOM_RM_11, "IMOM_RM_11", 210545686}, + {Nyxus::Feature2D::IMOM_RM_12, "IMOM_RM_12", 5925377592}, + {Nyxus::Feature2D::IMOM_RM_13, "IMOM_RM_13", 182290179472}, + {Nyxus::Feature2D::IMOM_RM_20, "IMOM_RM_20", 310000126}, + {Nyxus::Feature2D::IMOM_RM_21, "IMOM_RM_21", 6998259834}, + {Nyxus::Feature2D::IMOM_RM_22, "IMOM_RM_22", 196352705268}, + {Nyxus::Feature2D::IMOM_RM_23, "IMOM_RM_23", 6030684350556}, + {Nyxus::Feature2D::IMOM_RM_30, "IMOM_RM_30", 11405788056}, + {Nyxus::Feature2D::IMOM_CM_00, "IMOM_CM_00", 346635}, + {Nyxus::Feature2D::IMOM_CM_01, "IMOM_CM_01", 67720}, + {Nyxus::Feature2D::IMOM_CM_02, "IMOM_CM_02", 41456090}, + {Nyxus::Feature2D::IMOM_CM_03, "IMOM_CM_03", -145325666}, + {Nyxus::Feature2D::IMOM_CM_10, "IMOM_CM_10", 240984}, + {Nyxus::Feature2D::IMOM_CM_11, "IMOM_CM_11", -4045396}, + {Nyxus::Feature2D::IMOM_CM_12, "IMOM_CM_12", 57516022}, + {Nyxus::Feature2D::IMOM_CM_13, "IMOM_CM_13", -1233664876}, + {Nyxus::Feature2D::IMOM_CM_20, "IMOM_CM_20", 63143698}, + {Nyxus::Feature2D::IMOM_CM_21, "IMOM_CM_21", 32838808}, + {Nyxus::Feature2D::IMOM_CM_22, "IMOM_CM_22", 7407669574}, + {Nyxus::Feature2D::IMOM_CM_23, "IMOM_CM_23", -20794765652}, + {Nyxus::Feature2D::IMOM_CM_30, "IMOM_CM_30", -100592700}, + {Nyxus::Feature2D::IMOM_CM_31, "IMOM_CM_31", -1511475334}, + {Nyxus::Feature2D::IMOM_CM_32, "IMOM_CM_32", -1566202592}, + {Nyxus::Feature2D::IMOM_CM_33, "IMOM_CM_33", -370723933282}, + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_00, "IMOM_NRM_00", 1), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_01, "IMOM_NRM_01", 0.039397166363954135), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_02, "IMOM_NRM_02", 0.001897046009773198), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_03, "IMOM_NRM_03", 9.9517462450555541e-05), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_10, "IMOM_NRM_10", 0.045341630166175047), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_11, "IMOM_NRM_11", 0.0017522720110346945), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_12, "IMOM_NRM_12", 8.3759678499449274e-05), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_13, "IMOM_NRM_13", 4.3766925283775395e-06), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_20, "IMOM_NRM_20", 0.0025799842045067059), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_21, "IMOM_NRM_21", 9.8925677672061715e-05), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_22, "IMOM_NRM_22", 4.7143264687233126e-06), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_23, "IMOM_NRM_23", 2.4593093284379381e-07), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_30, "IMOM_NRM_30", 0.00016122941125190971), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_31, "IMOM_NRM_31", 6.1552927901407291e-06), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_32, "IMOM_NRM_32", 2.9283383602959163e-07), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_NRM_33, "IMOM_NRM_33", 1.5262053460086997e-08), + {Nyxus::Feature2D::IMOM_NCM_02, "IMOM_NCM_02", 0.00034501939970375497}, + {Nyxus::Feature2D::IMOM_NCM_03, "IMOM_NCM_03", -2.0542878277179582e-06}, + {Nyxus::Feature2D::IMOM_NCM_11, "IMOM_NCM_11", -3.3667914641346339e-05}, + {Nyxus::Feature2D::IMOM_NCM_12, "IMOM_NCM_12", 8.1303232350821154e-07}, + {Nyxus::Feature2D::IMOM_NCM_20, "IMOM_NCM_20", 0.00052551508786851807}, + {Nyxus::Feature2D::IMOM_NCM_21, "IMOM_NCM_21", 4.6420130323825322e-07}, + {Nyxus::Feature2D::IMOM_NCM_30, "IMOM_NCM_30", -1.4219536359618971e-06}, + {Nyxus::Feature2D::IMOM_HU1, "IMOM_HU1", 0.00087053448757227299}, + {Nyxus::Feature2D::IMOM_HU2, "IMOM_HU2", 3.7112807351259333e-08}, + {Nyxus::Feature2D::IMOM_HU3, "IMOM_HU3", 2.6788774435431954e-11}, + {Nyxus::Feature2D::IMOM_HU4, "IMOM_HU4", 2.8991603200922661e-12}, + {Nyxus::Feature2D::IMOM_HU5, "IMOM_HU5", -2.1393783155778043e-23}, + {Nyxus::Feature2D::IMOM_HU6, "IMOM_HU6", -2.0542878280693274e-06}, + {Nyxus::Feature2D::IMOM_HU7, "IMOM_HU7", 2.3835594243218353e-23}, +}; + +static const std::vector intensity_weighted_geomoment_expectations{ + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WRM_00, "IMOM_WRM_00", 512893.00982429727), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WRM_01, "IMOM_WRM_01", 12144895.632545877), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WRM_02, "IMOM_WRM_02", 317009217.47022206), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WRM_03, "IMOM_WRM_03", 8987339922.381422), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WRM_10, "IMOM_WRM_10", 14267758.335710838), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WRM_11, "IMOM_WRM_11", 340242564.82820618), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WRM_12, "IMOM_WRM_12", 8924143257.7546329), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WRM_20, "IMOM_WRM_20", 445196520.83852273), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WRM_21, "IMOM_WRM_21", 10672248980.453976), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WRM_30, "IMOM_WRM_30", 15212433464.582859), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WCM_02, "IMOM_WCM_02", 29664420.570163991), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WCM_03, "IMOM_WCM_03", 147284035.25422412), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WCM_11, "IMOM_WCM_11", 2678500.1290065008), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WCM_12, "IMOM_WCM_12", 19690079.853762936), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WCM_20, "IMOM_WCM_20", 48636574.87205068), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WCM_21, "IMOM_WCM_21", 34138173.79962717), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WCM_30, "IMOM_WCM_30", 259829644.49042335), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WNCM_02, "IMOM_WNCM_02", 0.00011276707339208047), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WNCM_03, "IMOM_WNCM_03", 7.8178750321206185e-07), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WNCM_11, "IMOM_WNCM_11", 1.0182117662266657e-05), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WNCM_12, "IMOM_WNCM_12", 1.0451545777075632e-07), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WNCM_20, "IMOM_WNCM_20", 0.00018488829725035266), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WNCM_21, "IMOM_WNCM_21", 1.8120631752764605e-07), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WNCM_30, "IMOM_WNCM_30", 1.3791825344547646e-06), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WHU1, "IMOM_WHU1", 0.00029765537064243316), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WHU2, "IMOM_WHU2", 5.6161730111679807e-09), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WHU3, "IMOM_WHU3", 1.1923046864432925e-12), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WHU4, "IMOM_WHU4", 3.1287168309169019e-12), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WHU5, "IMOM_WHU5", -5.2494915279842729e-24), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WHU6, "IMOM_WHU6", 7.8178750331489451e-07), + unvetted_no_direct_oracle_geomoment(Nyxus::Feature2D::IMOM_WHU7, "IMOM_WHU7", -5.6202519491182231e-24), +}; + +void test_2d_shape_geometric_moments_mixed_verifiable_and_unvetted() +{ + std::vector> fvals; + calculate_2d_geomoment_feature_values(fvals); + assert_2d_geomoment_features(fvals, shape_geomoment_expectations); +} + +void test_2d_shape_weighted_geometric_moments_unvetted_no_direct_oracle() +{ + std::vector> fvals; + calculate_2d_geomoment_feature_values(fvals); + assert_2d_geomoment_features(fvals, shape_weighted_geomoment_expectations); +} + +void test_2d_intensity_geometric_moments_mixed_verifiable_and_unvetted() +{ + std::vector> fvals; + calculate_2d_geomoment_feature_values(fvals); + assert_2d_geomoment_features(fvals, intensity_geomoment_expectations); +} + +void test_2d_intensity_weighted_geometric_moments_unvetted_no_direct_oracle() +{ + std::vector> fvals; + calculate_2d_geomoment_feature_values(fvals); + assert_2d_geomoment_features(fvals, intensity_weighted_geomoment_expectations); +} diff --git a/tests/test_2d_remaining_features.h b/tests/test_2d_remaining_features.h new file mode 100644 index 00000000..0874241a --- /dev/null +++ b/tests/test_2d_remaining_features.h @@ -0,0 +1,397 @@ +#pragma once + +#include + +#include +#include +#include +#include + +#include "../src/nyx/roi_cache.h" +#include "../src/nyx/features/basic_morphology.h" +#include "../src/nyx/features/caliper.h" +#include "../src/nyx/features/chords.h" +#include "../src/nyx/features/contour.h" +#include "../src/nyx/features/convex_hull.h" +#include "../src/nyx/features/erosion.h" +#include "../src/nyx/features/hexagonality_polygonality.h" +#include "../src/nyx/features/neighbors.h" +#include "../src/nyx/features/radial_distribution.h" +#include "../src/nyx/features/zernike.h" +#include "test_data.h" +#include "test_main_nyxus.h" + +static std::unordered_map remaining2d_truth{ + {"EROSIONS_2_VANISH_COMPLEMENT", 0.0}, + {"MIN_FERET_ANGLE", 40.0}, + {"MAX_FERET_ANGLE", 0.0}, + {"STAT_FERET_DIAM_MIN", 4.0}, + {"STAT_FERET_DIAM_MAX", 5.0}, + {"STAT_FERET_DIAM_MEAN", 4.9473684210526319}, + {"STAT_FERET_DIAM_MEDIAN", 5.0}, + {"STAT_FERET_DIAM_STDDEV", 0.22329687826943606}, + {"STAT_FERET_DIAM_MODE", 5.0}, + {"STAT_MARTIN_DIAM_MIN", 0.79999995380639899}, + {"STAT_MARTIN_DIAM_MAX", 5.0}, + {"STAT_MARTIN_DIAM_MEAN", 3.1314814727604796}, + {"STAT_MARTIN_DIAM_MEDIAN", 3.5}, + {"STAT_MARTIN_DIAM_STDDEV", 1.6662952583978845}, + {"STAT_MARTIN_DIAM_MODE", 1.0}, + {"STAT_NASSENSTEIN_DIAM_MIN", 0.0}, + {"STAT_NASSENSTEIN_DIAM_MAX", 5.0}, + {"STAT_NASSENSTEIN_DIAM_MEAN", 2.68842592930522}, + {"STAT_NASSENSTEIN_DIAM_MEDIAN", 3.5}, + {"STAT_NASSENSTEIN_DIAM_STDDEV", 2.1985188021518653}, + {"STAT_NASSENSTEIN_DIAM_MODE", 0.0}, + {"MAXCHORDS_MAX", 6.0}, + {"MAXCHORDS_MAX_ANG", 0.94247779607693793}, + {"MAXCHORDS_MIN", 3.0}, + {"MAXCHORDS_MIN_ANG", 0.94247779607693793}, + {"MAXCHORDS_MEDIAN", 4.0}, + {"MAXCHORDS_MEAN", 4.5500000000000007}, + {"MAXCHORDS_MODE", 4.0}, + {"MAXCHORDS_STDDEV", 0.94451324138833304}, + {"ALLCHORDS_MAX", 6.0}, + {"ALLCHORDS_MAX_ANG", 0.15707963267948966}, + {"ALLCHORDS_MIN", 1.0}, + {"ALLCHORDS_MIN_ANG", 0.15707963267948966}, + {"ALLCHORDS_MEDIAN", 4.0}, + {"ALLCHORDS_MEAN", 2.9134615384615379}, + {"ALLCHORDS_MODE", 4.0}, + {"ALLCHORDS_STDDEV", 1.3446086298393252}, + {"POLYGONALITY_AVE", 2.0833333333333357}, + {"HEXAGONALITY_AVE", 6.4262878058432173}, + {"HEXAGONALITY_STDDEV", 0.31438281411429858}, +}; + +static std::unordered_map> remaining2d_vector_truth{ + {"FRAC_AT_D", { + 0.038461538460059175, 0.0, 0.11538461538017751, 0.1538461538402367, + 0.3076923076804734, 0.0, 0.11538461538017751, 0.26923076922041422, + }}, + {"MEAN_FRAC", { + 50.999999948999999, 0.0, 53.333333315555556, 50.749999987312499, + 47.374999994078124, 0.0, 33.666666655444445, 21.999999996857142, + }}, + {"RADIAL_CV", { + 2.6457513106495707, 0.0, 1.298797520721114, 1.024429214739045, + 0.64750329537582818, 0.0, 1.3575192606324717, 1.3284260624865412, + }}, + {"ZERNIKE2D", { + 0.02049738595695693, 0.035831084484416686, 0.073953766599300461, + 0.035435050265597692, 0.092323797445497555, 0.011030627605166297, + 0.13199834370886107, 0.13453286019693309, 0.00788523106321295, + 0.082424064819857396, 0.049062071772591059, 0.0040585552756590825, + 0.14488178557089382, 0.23625456011991602, 0.038032570269059741, + 0.0011694758904577424, 0.016507094944884948, 0.10703041567067684, + 0.021302528534918392, 0.00061791897183974015, 0.10313303720229962, + 0.23275354391334316, 0.08692094259111556, 0.0063362223871874139, + 0.00016460740533666494, 0.085700825034398798, 0.15183975656312645, + 0.052012830525298454, 0.0045112452293896111, 0.00015124210515210458, + }}, +}; + +static Fsettings make_remaining2d_settings() +{ + Fsettings s; + s.resize(static_cast(NyxSetting::__COUNT__)); + s[static_cast(NyxSetting::SOFTNAN)].rval = 0.0; + s[static_cast(NyxSetting::TINY)].rval = 0.0; + s[static_cast(NyxSetting::SINGLEROI)].bval = false; + s[static_cast(NyxSetting::GREYDEPTH)].ival = 128; + s[static_cast(NyxSetting::PIXELSIZEUM)].rval = 2.0; + s[static_cast(NyxSetting::XYRES)].rval = 1.0; + s[static_cast(NyxSetting::PIXELDISTANCE)].ival = 1; + s[static_cast(NyxSetting::USEGPU)].bval = false; + s[static_cast(NyxSetting::VERBOSLVL)].ival = 0; + s[static_cast(NyxSetting::IBSI)].bval = false; + return s; +} + +static void calculate_remaining2d_shape_feature_values(std::vector>& fvals) +{ + Fsettings s = make_remaining2d_settings(); + + LR roidata(1201); + load_masked_test_roi_data( + roidata, + shape2d_morphology_intensity, + shape2d_morphology_mask, + sizeof(shape2d_morphology_mask) / sizeof(NyxusPixel)); + roidata.initialize_fvals(); + + BasicMorphologyFeatures basic; + basic.calculate(roidata, s); + basic.save_value(roidata.fvals); + + ContourFeature contour; + contour.calculate(roidata, s); + contour.save_value(roidata.fvals); + + ConvexHullFeature hull; + hull.calculate(roidata, s); + hull.save_value(roidata.fvals); + + CaliperFeretFeature feret; + feret.calculate(roidata, s); + feret.save_value(roidata.fvals); + + CaliperMartinFeature martin; + martin.calculate(roidata, s); + martin.save_value(roidata.fvals); + + CaliperNassensteinFeature nassenstein; + nassenstein.calculate(roidata, s); + nassenstein.save_value(roidata.fvals); + + ChordsFeature chords; + chords.calculate(roidata, s); + chords.save_value(roidata.fvals); + + ErosionPixelsFeature erosion; + erosion.calculate(roidata, s); + erosion.save_value(roidata.fvals); + + RadialDistributionFeature radial; + radial.calculate(roidata, s); + radial.save_value(roidata.fvals); + + ZernikeFeature zernike; + zernike.calculate(roidata, s); + zernike.save_value(roidata.fvals); + + fvals = roidata.fvals; +} + +static void calculate_remaining2d_polygonality_feature_values(std::unordered_map& roiData) +{ + Fsettings s = make_remaining2d_settings(); + s[static_cast(NyxSetting::PIXELSIZEUM)].rval = 1.0; + std::unordered_set uniqueLabels; + + for (const auto& px : neighborhood2d_scene_labels) + { + int label = static_cast(px.intensity); + uniqueLabels.insert(label); + + auto [it, inserted] = roiData.try_emplace(label, label); + LR& roi = it->second; + + if (inserted) + init_label_record_3(roi, static_cast(px.x), static_cast(px.y), 1); + else + update_label_record_3(roi, static_cast(px.x), static_cast(px.y), 1); + + roi.raw_pixels.push_back(Pixel2(static_cast(px.x), static_cast(px.y), static_cast(1))); + } + + BasicMorphologyFeatures basic; + ContourFeature contour; + ConvexHullFeature hull; + CaliperFeretFeature feret; + for (auto& item : roiData) + { + LR& roi = item.second; + roi.make_nonanisotropic_aabb(); + roi.aux_image_matrix = ImageMatrix(roi.raw_pixels); + roi.initialize_fvals(); + + basic.calculate(roi, s); + basic.save_value(roi.fvals); + + contour.calculate(roi, s); + contour.save_value(roi.fvals); + + hull.calculate(roi, s); + hull.save_value(roi.fvals); + + feret.calculate(roi, s); + feret.save_value(roi.fvals); + } + + NeighborsFeature::manual_reduce(roiData, s, uniqueLabels); + + HexagonalityPolygonalityFeature hexpoly; + for (auto& item : roiData) + { + hexpoly.calculate(item.second, s); + hexpoly.save_value(item.second.fvals); + } +} + +static void assert_unvetted_no_direct_oracle_remaining2d_feature( + const std::vector>& fvals, + Nyxus::Feature2D feature, + const std::string& feature_name, + double frac_tolerance = 1000.0) +{ + SCOPED_TRACE(std::string("UNVETTED_NO_DIRECT_ORACLE__") + feature_name); + ASSERT_TRUE(remaining2d_truth.count(feature_name) > 0); + ASSERT_TRUE(agrees_gt(fvals[static_cast(feature)][0], remaining2d_truth[feature_name], frac_tolerance)); +} + +static void assert_verifiable_with_3p_builtin_oracle_remaining2d_feature( + const std::vector>& fvals, + Nyxus::Feature2D feature, + const std::string& feature_name, + double frac_tolerance = 1000.0) +{ + SCOPED_TRACE(std::string("VERIFIABLE_WITH_3P_BUILTIN_ORACLE__") + feature_name); + ASSERT_TRUE(remaining2d_truth.count(feature_name) > 0); + ASSERT_TRUE(agrees_gt(fvals[static_cast(feature)][0], remaining2d_truth[feature_name], frac_tolerance)); +} + +static void assert_unvetted_no_direct_oracle_remaining2d_polygonality_feature( + const std::unordered_map& roiData, + Nyxus::Feature2D feature, + const std::string& feature_name) +{ + SCOPED_TRACE(std::string("UNVETTED_NO_DIRECT_ORACLE__") + feature_name); + const double actual = roiData.at(1).fvals[static_cast(feature)][0]; + ASSERT_GT(actual, 0.0); +} + +static void assert_unvetted_no_direct_oracle_remaining2d_polygonality_score( + const std::unordered_map& roiData, + Nyxus::Feature2D feature, + const std::string& feature_name) +{ + assert_unvetted_no_direct_oracle_remaining2d_polygonality_feature(roiData, feature, feature_name); + ASSERT_LE(roiData.at(1).fvals[static_cast(feature)][0], 10.0); +} + +static void assert_remaining2d_polygonality_no_value_for_sparse_neighbors( + const std::unordered_map& roiData, + Nyxus::Feature2D feature) +{ + for (int label : {2, 3, 4, 5}) + ASSERT_EQ(roiData.at(label).fvals[static_cast(feature)][0], -1.0); +} + +static void assert_unvetted_no_direct_oracle_remaining2d_vector_feature( + const std::vector>& fvals, + Nyxus::Feature2D feature, + const std::string& feature_name, + double abs_tolerance = 1e-9) +{ + SCOPED_TRACE(std::string("UNVETTED_NO_DIRECT_ORACLE__") + feature_name); + ASSERT_TRUE(remaining2d_vector_truth.count(feature_name) > 0); + const auto& actual = fvals[static_cast(feature)]; + const auto& expected = remaining2d_vector_truth[feature_name]; + ASSERT_EQ(actual.size(), expected.size()); + for (size_t i = 0; i < expected.size(); ++i) + ASSERT_NEAR(actual[i], expected[i], abs_tolerance) << feature_name << "[" << i << "]"; +} + +static void assert_verifiable_with_3p_builtin_oracle_remaining2d_vector_feature( + const std::vector>& fvals, + Nyxus::Feature2D feature, + const std::string& feature_name, + double abs_tolerance = 1e-9) +{ + SCOPED_TRACE(std::string("VERIFIABLE_WITH_3P_BUILTIN_ORACLE__") + feature_name); + ASSERT_TRUE(remaining2d_vector_truth.count(feature_name) > 0); + const auto& actual = fvals[static_cast(feature)]; + const auto& expected = remaining2d_vector_truth[feature_name]; + ASSERT_EQ(actual.size(), expected.size()); + for (size_t i = 0; i < expected.size(); ++i) + ASSERT_NEAR(actual[i], expected[i], abs_tolerance) << feature_name << "[" << i << "]"; +} + +void test_remaining2d_verifiable_with_3p_builtin_oracle_erosion_complement_feature() +{ + std::vector> fvals; + calculate_remaining2d_shape_feature_values(fvals); + + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::EROSIONS_2_VANISH_COMPLEMENT, "EROSIONS_2_VANISH_COMPLEMENT"); +} + +void test_remaining2d_verifiable_with_3p_builtin_oracle_caliper_features() +{ + std::vector> fvals; + calculate_remaining2d_shape_feature_values(fvals); + + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::MIN_FERET_ANGLE, "MIN_FERET_ANGLE"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::MAX_FERET_ANGLE, "MAX_FERET_ANGLE"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_FERET_DIAM_MIN, "STAT_FERET_DIAM_MIN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_FERET_DIAM_MAX, "STAT_FERET_DIAM_MAX"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_FERET_DIAM_MEAN, "STAT_FERET_DIAM_MEAN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_FERET_DIAM_MEDIAN, "STAT_FERET_DIAM_MEDIAN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_FERET_DIAM_STDDEV, "STAT_FERET_DIAM_STDDEV"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_FERET_DIAM_MODE, "STAT_FERET_DIAM_MODE"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_MARTIN_DIAM_MIN, "STAT_MARTIN_DIAM_MIN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_MARTIN_DIAM_MAX, "STAT_MARTIN_DIAM_MAX"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_MARTIN_DIAM_MEAN, "STAT_MARTIN_DIAM_MEAN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_MARTIN_DIAM_MEDIAN, "STAT_MARTIN_DIAM_MEDIAN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_MARTIN_DIAM_STDDEV, "STAT_MARTIN_DIAM_STDDEV"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_MARTIN_DIAM_MODE, "STAT_MARTIN_DIAM_MODE"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_NASSENSTEIN_DIAM_MIN, "STAT_NASSENSTEIN_DIAM_MIN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_NASSENSTEIN_DIAM_MAX, "STAT_NASSENSTEIN_DIAM_MAX"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_NASSENSTEIN_DIAM_MEAN, "STAT_NASSENSTEIN_DIAM_MEAN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_NASSENSTEIN_DIAM_MEDIAN, "STAT_NASSENSTEIN_DIAM_MEDIAN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_NASSENSTEIN_DIAM_STDDEV, "STAT_NASSENSTEIN_DIAM_STDDEV"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::STAT_NASSENSTEIN_DIAM_MODE, "STAT_NASSENSTEIN_DIAM_MODE"); +} + +void test_remaining2d_verifiable_with_3p_builtin_oracle_chord_stat_features() +{ + std::vector> fvals; + calculate_remaining2d_shape_feature_values(fvals); + + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::MAXCHORDS_MAX, "MAXCHORDS_MAX"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::MAXCHORDS_MIN, "MAXCHORDS_MIN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::MAXCHORDS_MEDIAN, "MAXCHORDS_MEDIAN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::MAXCHORDS_MEAN, "MAXCHORDS_MEAN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::MAXCHORDS_MODE, "MAXCHORDS_MODE"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::MAXCHORDS_STDDEV, "MAXCHORDS_STDDEV"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::ALLCHORDS_MAX, "ALLCHORDS_MAX"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::ALLCHORDS_MIN, "ALLCHORDS_MIN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::ALLCHORDS_MEDIAN, "ALLCHORDS_MEDIAN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::ALLCHORDS_MEAN, "ALLCHORDS_MEAN"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::ALLCHORDS_MODE, "ALLCHORDS_MODE"); + assert_verifiable_with_3p_builtin_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::ALLCHORDS_STDDEV, "ALLCHORDS_STDDEV"); +} + +void test_remaining2d_unvetted_no_direct_oracle_chord_angle_features() +{ + std::vector> fvals; + calculate_remaining2d_shape_feature_values(fvals); + + assert_unvetted_no_direct_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::MAXCHORDS_MAX_ANG, "MAXCHORDS_MAX_ANG"); + assert_unvetted_no_direct_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::MAXCHORDS_MIN_ANG, "MAXCHORDS_MIN_ANG"); + assert_unvetted_no_direct_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::ALLCHORDS_MAX_ANG, "ALLCHORDS_MAX_ANG"); + assert_unvetted_no_direct_oracle_remaining2d_feature(fvals, Nyxus::Feature2D::ALLCHORDS_MIN_ANG, "ALLCHORDS_MIN_ANG"); +} + +void test_remaining2d_unvetted_no_direct_oracle_polygonality_hexagonality_features() +{ + std::unordered_map roiData; + calculate_remaining2d_polygonality_feature_values(roiData); + + ASSERT_EQ(roiData.at(1).fvals[static_cast(Nyxus::Feature2D::NUM_NEIGHBORS)][0], 4.0); + assert_unvetted_no_direct_oracle_remaining2d_polygonality_score(roiData, Nyxus::Feature2D::POLYGONALITY_AVE, "POLYGONALITY_AVE"); + assert_unvetted_no_direct_oracle_remaining2d_polygonality_score(roiData, Nyxus::Feature2D::HEXAGONALITY_AVE, "HEXAGONALITY_AVE"); + assert_unvetted_no_direct_oracle_remaining2d_polygonality_feature(roiData, Nyxus::Feature2D::HEXAGONALITY_STDDEV, "HEXAGONALITY_STDDEV"); + + assert_remaining2d_polygonality_no_value_for_sparse_neighbors(roiData, Nyxus::Feature2D::POLYGONALITY_AVE); + assert_remaining2d_polygonality_no_value_for_sparse_neighbors(roiData, Nyxus::Feature2D::HEXAGONALITY_AVE); + assert_remaining2d_polygonality_no_value_for_sparse_neighbors(roiData, Nyxus::Feature2D::HEXAGONALITY_STDDEV); +} + +void test_remaining2d_unvetted_no_direct_oracle_radial_distribution_features() +{ + std::vector> fvals; + calculate_remaining2d_shape_feature_values(fvals); + + assert_unvetted_no_direct_oracle_remaining2d_vector_feature(fvals, Nyxus::Feature2D::FRAC_AT_D, "FRAC_AT_D"); + assert_unvetted_no_direct_oracle_remaining2d_vector_feature(fvals, Nyxus::Feature2D::MEAN_FRAC, "MEAN_FRAC"); + assert_unvetted_no_direct_oracle_remaining2d_vector_feature(fvals, Nyxus::Feature2D::RADIAL_CV, "RADIAL_CV"); +} + +void test_remaining2d_verifiable_with_3p_builtin_oracle_zernike2d_feature() +{ + std::vector> fvals; + calculate_remaining2d_shape_feature_values(fvals); + + assert_verifiable_with_3p_builtin_oracle_remaining2d_vector_feature(fvals, Nyxus::Feature2D::ZERNIKE2D, "ZERNIKE2D"); +} diff --git a/tests/test_all.cc b/tests/test_all.cc index 82f138db..dcc90842 100644 --- a/tests/test_all.cc +++ b/tests/test_all.cc @@ -6,6 +6,8 @@ #include "test_pixel_intensity_features.h" #include "test_morphology_features.h" #include "test_shape_morphology_2d.h" +#include "test_2d_geometric_moments.h" +#include "test_2d_remaining_features.h" #include "test_neighbors_2d.h" #include "test_initialization.h" #include "test_ibsi_glcm.h" @@ -665,13 +667,13 @@ TEST(TEST_NYXUS, TEST_3NGLDM_DCENE) { //***** Gabor regression ***** -TEST(TEST_NYXUS, TEST_GABOR){ - test_gabor(); - - #ifdef USE_GPU - test_gabor(true); - #endif -} +TEST(TEST_NYXUS, TEST_UNVETTED_NO_DIRECT_ORACLE_GABOR){ + test_unvetted_no_direct_oracle_gabor(); + + #ifdef USE_GPU + test_unvetted_no_direct_oracle_gabor(true); + #endif +} //***** helper functionality ***** @@ -753,15 +755,15 @@ TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_KURTOSIS) ASSERT_NO_THROW(test_pixel_intensity_pearson_kurtosis()); } -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_HYPERSKEWNESS) +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_HYPERSKEWNESS) { - ASSERT_NO_THROW(test_pixel_intensity_hyperskewness()); + ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_hyperskewness()); } -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_HYPERFLATNESS) -{ - ASSERT_NO_THROW(test_pixel_intensity_hyperflatness()); -} +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_HYPERFLATNESS) +{ + ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_hyperflatness()); +} TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MAD) { @@ -773,9 +775,9 @@ TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_MEDIAN_ABSOLUTE_DEVIATION) ASSERT_NO_THROW(test_pixel_intensity_median_absolute_deviation()); } -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_ROBUST_MEAN) +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_ROBUST_MEAN) { - ASSERT_NO_THROW(test_pixel_intensity_robust_mean()); + ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_robust_mean()); } TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_ROBUST_MAD) @@ -808,9 +810,9 @@ TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_UNIFORMITY) ASSERT_NO_THROW(test_pixel_intensity_uniformity()); } -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_UNIFORMITY_PIU) +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_UNIFORMITY_PIU) { - ASSERT_NO_THROW(test_pixel_intensity_uniformity_piu()); + ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_uniformity_piu()); } TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_PERCENTILES_IQR) @@ -823,9 +825,9 @@ TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_QCOD) ASSERT_NO_THROW(test_pixel_intensity_qcod()); } -TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_COVERED_IMAGE_INTENSITY_RANGE) +TEST(TEST_NYXUS, TEST_PIXEL_INTENSITY_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_COVERED_IMAGE_INTENSITY_RANGE) { - ASSERT_NO_THROW(test_pixel_intensity_covered_image_intensity_range()); + ASSERT_NO_THROW(test_pixel_intensity_verifiable_with_3p_builtin_oracle_covered_image_intensity_range()); } @@ -851,14 +853,19 @@ 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) +{ + ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_contour_diameter_equal_perimeter()); +} + TEST(TEST_NYXUS, TEST_SHAPE2D_CONVEX_HULL_FEATURES) { ASSERT_NO_THROW(test_shape2d_convex_hull_features()); } -TEST(TEST_NYXUS, TEST_SHAPE2D_EXTREMA_FEATURES) +TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_EXTREMA_FEATURES) { - ASSERT_NO_THROW(test_shape2d_extrema_features()); + ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_extrema_features()); } TEST(TEST_NYXUS, TEST_SHAPE2D_MISC_FEATURES) @@ -866,6 +873,76 @@ TEST(TEST_NYXUS, TEST_SHAPE2D_MISC_FEATURES) ASSERT_NO_THROW(test_shape2d_misc_shape_features()); } +TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_FRACTAL_CIRCLE_FEATURES) +{ + ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_fractal_circle_features()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_UNVETTED_NO_DIRECT_ORACLE_RADIUS_FEATURES) +{ + ASSERT_NO_THROW(test_shape2d_unvetted_no_direct_oracle_radius_features()); +} + +TEST(TEST_NYXUS, TEST_2D_SHAPE_GEOMETRIC_MOMENTS_MIXED_VERIFIABLE_AND_UNVETTED) +{ + ASSERT_NO_THROW(test_2d_shape_geometric_moments_mixed_verifiable_and_unvetted()); +} + +TEST(TEST_NYXUS, TEST_2D_SHAPE_WEIGHTED_GEOMETRIC_MOMENTS_UNVETTED_NO_DIRECT_ORACLE) +{ + ASSERT_NO_THROW(test_2d_shape_weighted_geometric_moments_unvetted_no_direct_oracle()); +} + +TEST(TEST_NYXUS, TEST_2D_INTENSITY_GEOMETRIC_MOMENTS_MIXED_VERIFIABLE_AND_UNVETTED) +{ + ASSERT_NO_THROW(test_2d_intensity_geometric_moments_mixed_verifiable_and_unvetted()); +} + +TEST(TEST_NYXUS, TEST_2D_INTENSITY_WEIGHTED_GEOMETRIC_MOMENTS_UNVETTED_NO_DIRECT_ORACLE) +{ + ASSERT_NO_THROW(test_2d_intensity_weighted_geometric_moments_unvetted_no_direct_oracle()); +} + +TEST(TEST_NYXUS, TEST_SHAPE2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_GEODETIC_THICKNESS_EROSION) +{ + ASSERT_NO_THROW(test_shape2d_verifiable_with_3p_builtin_oracle_geodetic_thickness_erosion_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_EROSION_COMPLEMENT) +{ + ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_erosion_complement_feature()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_CALIPER_FEATURES) +{ + ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_caliper_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_CHORD_STAT_FEATURES) +{ + ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_chord_stat_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_UNVETTED_NO_DIRECT_ORACLE_CHORD_ANGLE_FEATURES) +{ + ASSERT_NO_THROW(test_remaining2d_unvetted_no_direct_oracle_chord_angle_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_UNVETTED_NO_DIRECT_ORACLE_POLYGONALITY_HEXAGONALITY) +{ + ASSERT_NO_THROW(test_remaining2d_unvetted_no_direct_oracle_polygonality_hexagonality_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_UNVETTED_NO_DIRECT_ORACLE_RADIAL_DISTRIBUTION) +{ + ASSERT_NO_THROW(test_remaining2d_unvetted_no_direct_oracle_radial_distribution_features()); +} + +TEST(TEST_NYXUS, TEST_REMAINING2D_VERIFIABLE_WITH_3P_BUILTIN_ORACLE_ZERNIKE2D) +{ + ASSERT_NO_THROW(test_remaining2d_verifiable_with_3p_builtin_oracle_zernike2d_feature()); +} + TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_COUNTS_TOUCHING) { ASSERT_NO_THROW(test_neighborhood2d_counts_and_touching()); @@ -876,9 +953,14 @@ TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_CLOSEST_NEIGHBORS) ASSERT_NO_THROW(test_neighborhood2d_closest_neighbors()); } -TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_ANGLE_STATS) +TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_UNVETTED_NO_DIRECT_ORACLE_CLOSEST_NEIGHBOR_ANGLES) +{ + ASSERT_NO_THROW(test_neighborhood2d_unvetted_no_direct_oracle_closest_neighbor_angles()); +} + +TEST(TEST_NYXUS, TEST_NEIGHBORHOOD2D_UNVETTED_NO_DIRECT_ORACLE_ANGLE_STATS) { - ASSERT_NO_THROW(test_neighborhood2d_neighbor_angle_stats()); + ASSERT_NO_THROW(test_neighborhood2d_unvetted_no_direct_oracle_neighbor_angle_stats()); } @@ -1640,9 +1722,9 @@ TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCP) ASSERT_NO_THROW(test_ibsi_NGLDM_DCP()); } -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_GLM) +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_UNVETTED_NO_DIRECT_ORACLE_GLM) { - ASSERT_NO_THROW(test_ibsi_NGLDM_GLM()); + ASSERT_NO_THROW(test_ibsi_NGLDM_unvetted_no_direct_oracle_GLM()); } TEST(TEST_NYXUS, TEST_IBSI_NGLDM_GLV) @@ -1650,9 +1732,9 @@ TEST(TEST_NYXUS, TEST_IBSI_NGLDM_GLV) ASSERT_NO_THROW(test_ibsi_NGLDM_GLV()); } -TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCM) +TEST(TEST_NYXUS, TEST_IBSI_NGLDM_UNVETTED_NO_DIRECT_ORACLE_DCM) { - ASSERT_NO_THROW(test_ibsi_NGLDM_DCM()); + ASSERT_NO_THROW(test_ibsi_NGLDM_unvetted_no_direct_oracle_DCM()); } TEST(TEST_NYXUS, TEST_IBSI_NGLDM_DCV) @@ -2042,9 +2124,9 @@ TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZP) ASSERT_NO_THROW(test_ibsi_GLDZM_ZP()); } -TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_GLM) +TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_UNVETTED_NO_DIRECT_ORACLE_GLM) { - ASSERT_NO_THROW(test_ibsi_GLDZM_GLM()); + ASSERT_NO_THROW(test_ibsi_GLDZM_unvetted_no_direct_oracle_GLM()); } TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_GLV) @@ -2052,9 +2134,9 @@ TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_GLV) ASSERT_NO_THROW(test_ibsi_GLDZM_GLV()); } -TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZDM) +TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_UNVETTED_NO_DIRECT_ORACLE_ZDM) { - ASSERT_NO_THROW(test_ibsi_GLDZM_ZDM()); + ASSERT_NO_THROW(test_ibsi_GLDZM_unvetted_no_direct_oracle_ZDM()); } TEST(TEST_NYXUS, TEST_GLDZM_MATRIX_ZDV) diff --git a/tests/test_gabor.cc b/tests/test_gabor.cc index e1e57014..f52a95e8 100644 --- a/tests/test_gabor.cc +++ b/tests/test_gabor.cc @@ -9,8 +9,10 @@ using namespace std; using namespace Nyxus; -void test_gabor(bool gpu) +void test_unvetted_no_direct_oracle_gabor(bool gpu) { + SCOPED_TRACE("UNVETTED_NO_DIRECT_ORACLE__GABOR"); + for(int i = 0; i < dsb_data.size(); ++i) { LR roidata; diff --git a/tests/test_gabor.h b/tests/test_gabor.h index 41b0c400..b20b7f59 100644 --- a/tests/test_gabor.h +++ b/tests/test_gabor.h @@ -3,4 +3,4 @@ #include "../src/nyx/globals.h" -void test_gabor(bool gpu=false); \ No newline at end of file +void test_unvetted_no_direct_oracle_gabor(bool gpu=false); diff --git a/tests/test_ibsi_gldzm.h b/tests/test_ibsi_gldzm.h index 3362b7cc..01542c2d 100644 --- a/tests/test_ibsi_gldzm.h +++ b/tests/test_ibsi_gldzm.h @@ -247,8 +247,9 @@ void test_ibsi_GLDZM_ZP() test_ibsi_gldzm_feature(Nyxus::Feature2D::GLDZM_ZP, "GLDZM_ZP"); } -void test_ibsi_GLDZM_GLM() +void test_ibsi_GLDZM_unvetted_no_direct_oracle_GLM() { + SCOPED_TRACE("UNVETTED_NO_DIRECT_ORACLE__GLDZM_GLM"); test_ibsi_gldzm_feature(Nyxus::Feature2D::GLDZM_GLM, "GLDZM_GLM"); } @@ -257,8 +258,9 @@ void test_ibsi_GLDZM_GLV() test_ibsi_gldzm_feature(Nyxus::Feature2D::GLDZM_GLV, "GLDZM_GLV"); } -void test_ibsi_GLDZM_ZDM() +void test_ibsi_GLDZM_unvetted_no_direct_oracle_ZDM() { + SCOPED_TRACE("UNVETTED_NO_DIRECT_ORACLE__GLDZM_ZDM"); test_ibsi_gldzm_feature(Nyxus::Feature2D::GLDZM_ZDM, "GLDZM_ZDM"); } diff --git a/tests/test_ibsi_ngldm.h b/tests/test_ibsi_ngldm.h index eb029d39..39cd1f54 100644 --- a/tests/test_ibsi_ngldm.h +++ b/tests/test_ibsi_ngldm.h @@ -332,8 +332,9 @@ void test_ibsi_NGLDM_DCP() test_ibsi_ngldm_feature(Nyxus::Feature2D::NGLDM_DCP, "NGLDM_DCP"); } -void test_ibsi_NGLDM_GLM() +void test_ibsi_NGLDM_unvetted_no_direct_oracle_GLM() { + SCOPED_TRACE("UNVETTED_NO_DIRECT_ORACLE__NGLDM_GLM"); test_ibsi_ngldm_feature(Nyxus::Feature2D::NGLDM_GLM, "NGLDM_GLM"); } @@ -342,8 +343,9 @@ void test_ibsi_NGLDM_GLV() test_ibsi_ngldm_feature(Nyxus::Feature2D::NGLDM_GLV, "NGLDM_GLV"); } -void test_ibsi_NGLDM_DCM() +void test_ibsi_NGLDM_unvetted_no_direct_oracle_DCM() { + SCOPED_TRACE("UNVETTED_NO_DIRECT_ORACLE__NGLDM_DCM"); test_ibsi_ngldm_feature(Nyxus::Feature2D::NGLDM_DCM, "NGLDM_DCM"); } diff --git a/tests/test_neighbors_2d.h b/tests/test_neighbors_2d.h index f794b869..9df2be92 100644 --- a/tests/test_neighbors_2d.h +++ b/tests/test_neighbors_2d.h @@ -141,6 +141,17 @@ static void assert_neighbor2d_feature( ASSERT_TRUE(agrees_gt(roiData.at(label).fvals[static_cast(feature)][0], neighborhood2d_truth[label][feature_name], frac_tolerance)); } +static void assert_unvetted_no_direct_oracle_neighbor2d_feature( + const std::unordered_map& roiData, + int label, + Nyxus::Feature2D feature, + const std::string& feature_name, + double frac_tolerance = 1000.0) +{ + SCOPED_TRACE(std::string("UNVETTED_NO_DIRECT_ORACLE__") + feature_name); + assert_neighbor2d_feature(roiData, label, feature, feature_name, frac_tolerance); +} + void test_neighborhood2d_counts_and_touching() { std::unordered_map roiData; @@ -161,21 +172,31 @@ void test_neighborhood2d_closest_neighbors() for (int label : {1, 2, 3, 4, 5}) { assert_neighbor2d_feature(roiData, label, Nyxus::Feature2D::CLOSEST_NEIGHBOR1_DIST, "CLOSEST_NEIGHBOR1_DIST"); - assert_neighbor2d_feature(roiData, label, Nyxus::Feature2D::CLOSEST_NEIGHBOR1_ANG, "CLOSEST_NEIGHBOR1_ANG"); assert_neighbor2d_feature(roiData, label, Nyxus::Feature2D::CLOSEST_NEIGHBOR2_DIST, "CLOSEST_NEIGHBOR2_DIST"); - assert_neighbor2d_feature(roiData, label, Nyxus::Feature2D::CLOSEST_NEIGHBOR2_ANG, "CLOSEST_NEIGHBOR2_ANG"); } } -void test_neighborhood2d_neighbor_angle_stats() +void test_neighborhood2d_unvetted_no_direct_oracle_closest_neighbor_angles() +{ + std::unordered_map roiData; + calculate_neighborhood2d_feature_values(roiData); + + for (int label : {1, 2, 3, 4, 5}) + { + assert_unvetted_no_direct_oracle_neighbor2d_feature(roiData, label, Nyxus::Feature2D::CLOSEST_NEIGHBOR1_ANG, "CLOSEST_NEIGHBOR1_ANG"); + assert_unvetted_no_direct_oracle_neighbor2d_feature(roiData, label, Nyxus::Feature2D::CLOSEST_NEIGHBOR2_ANG, "CLOSEST_NEIGHBOR2_ANG"); + } +} + +void test_neighborhood2d_unvetted_no_direct_oracle_neighbor_angle_stats() { std::unordered_map roiData; calculate_neighborhood2d_feature_values(roiData); for (int label : {1, 2, 3, 4, 5}) { - assert_neighbor2d_feature(roiData, label, Nyxus::Feature2D::ANG_BW_NEIGHBORS_MEAN, "ANG_BW_NEIGHBORS_MEAN"); - assert_neighbor2d_feature(roiData, label, Nyxus::Feature2D::ANG_BW_NEIGHBORS_STDDEV, "ANG_BW_NEIGHBORS_STDDEV"); - assert_neighbor2d_feature(roiData, label, Nyxus::Feature2D::ANG_BW_NEIGHBORS_MODE, "ANG_BW_NEIGHBORS_MODE"); + assert_unvetted_no_direct_oracle_neighbor2d_feature(roiData, label, Nyxus::Feature2D::ANG_BW_NEIGHBORS_MEAN, "ANG_BW_NEIGHBORS_MEAN"); + assert_unvetted_no_direct_oracle_neighbor2d_feature(roiData, label, Nyxus::Feature2D::ANG_BW_NEIGHBORS_STDDEV, "ANG_BW_NEIGHBORS_STDDEV"); + assert_unvetted_no_direct_oracle_neighbor2d_feature(roiData, label, Nyxus::Feature2D::ANG_BW_NEIGHBORS_MODE, "ANG_BW_NEIGHBORS_MODE"); } } diff --git a/tests/test_pixel_intensity_features.h b/tests/test_pixel_intensity_features.h index 639332b9..4507e718 100644 --- a/tests/test_pixel_intensity_features.h +++ b/tests/test_pixel_intensity_features.h @@ -248,11 +248,13 @@ void test_pixel_intensity_pearson_kurtosis() ASSERT_TRUE(agrees_gt(fvals[(int)Nyxus::Feature2D::KURTOSIS][0], 1.927888720710090)); } -void test_pixel_intensity_hyperskewness() -{ - // Feed data to the ROI - Dataset ds; - ds.dataset_props.push_back(SlideProps("","")); +void test_pixel_intensity_verifiable_with_3p_builtin_oracle_hyperskewness() +{ + SCOPED_TRACE("VERIFIABLE_WITH_3P_BUILTIN_ORACLE__HYPERSKEWNESS"); + + // Feed data to the ROI + Dataset ds; + ds.dataset_props.push_back(SlideProps("","")); LR roidata(100); // dummy label 100 roidata.slide_idx = -1; // we don't have a real slide for this test ROI @@ -274,11 +276,13 @@ void test_pixel_intensity_hyperskewness() ASSERT_TRUE(agrees_gt(roidata.fvals[(int)Nyxus::Feature2D::HYPERSKEWNESS][0], 1.978293086605381)); } -void test_pixel_intensity_hyperflatness() -{ - // Feed data to the ROI - Dataset ds; - ds.dataset_props.push_back(SlideProps("","")); +void test_pixel_intensity_verifiable_with_3p_builtin_oracle_hyperflatness() +{ + SCOPED_TRACE("VERIFIABLE_WITH_3P_BUILTIN_ORACLE__HYPERFLATNESS"); + + // Feed data to the ROI + Dataset ds; + ds.dataset_props.push_back(SlideProps("","")); LR roidata(100); // dummy label 100 roidata.slide_idx = -1; // we don't have a real slide for this test ROI @@ -476,11 +480,13 @@ void test_pixel_intensity_uniformity() ASSERT_TRUE(agrees_gt(roidata.fvals[(int)Nyxus::Feature2D::UNIFORMITY][0], 0.0647664, 100)); // Using 1% tolerance vs MATLAB } -void test_pixel_intensity_uniformity_piu() -{ - // Feed data to the ROI - Dataset ds; - ds.dataset_props.push_back(SlideProps("","")); +void test_pixel_intensity_verifiable_with_3p_builtin_oracle_uniformity_piu() +{ + SCOPED_TRACE("VERIFIABLE_WITH_3P_BUILTIN_ORACLE__UNIFORMITY_PIU"); + + // Feed data to the ROI + Dataset ds; + ds.dataset_props.push_back(SlideProps("","")); LR roidata(100); // dummy label 100 roidata.slide_idx = -1; // we don't have a real slide for this test ROI @@ -527,8 +533,10 @@ void test_pixel_intensity_cov() ASSERT_TRUE(agrees_gt(fvals[(int)Nyxus::Feature2D::COV][0], 4.523365498399634e-01)); } -void test_pixel_intensity_covered_image_intensity_range() +void test_pixel_intensity_verifiable_with_3p_builtin_oracle_covered_image_intensity_range() { + SCOPED_TRACE("VERIFIABLE_WITH_3P_BUILTIN_ORACLE__COVERED_IMAGE_INTENSITY_RANGE"); + std::vector> fvals; calculate_pixel_intensity_feature_values(fvals, Fsettings(), 0, 0.0, 65535.0); @@ -551,8 +559,10 @@ void test_pixel_intensity_qcod() ASSERT_TRUE(agrees_gt(fvals[(int)Nyxus::Feature2D::QCOD][0], 4.119607630640470e-01)); } -void test_pixel_intensity_robust_mean() +void test_pixel_intensity_verifiable_with_3p_builtin_oracle_robust_mean() { + SCOPED_TRACE("VERIFIABLE_WITH_3P_BUILTIN_ORACLE__ROBUST_MEAN"); + std::vector> fvals; calculate_pixel_intensity_feature_values(fvals); diff --git a/tests/test_shape_morphology_2d.h b/tests/test_shape_morphology_2d.h index 6e294339..ad36ce6d 100644 --- a/tests/test_shape_morphology_2d.h +++ b/tests/test_shape_morphology_2d.h @@ -16,6 +16,8 @@ #include "../src/nyx/features/euler_number.h" #include "../src/nyx/features/fractal_dim.h" #include "../src/nyx/features/circle.h" +#include "../src/nyx/features/geodetic_len_thickness.h" +#include "../src/nyx/features/erosion.h" #include "test_data.h" #include "test_main_nyxus.h" @@ -60,6 +62,9 @@ static std::unordered_map shape2d_truth{ {"ROI_RADIUS_MEAN", 1.07692307692308}, {"ROI_RADIUS_MAX", 4.0}, {"ROI_RADIUS_MEDIAN", 1.0}, + {"GEODETIC_LENGTH", 10.0}, + {"THICKNESS", 3.0}, + {"EROSIONS_2_VANISH", 1.0}, {"EXTREMA_P1_X", 2.0}, {"EXTREMA_P1_Y", 0.0}, {"EXTREMA_P2_X", 3.0}, @@ -143,6 +148,14 @@ static void calculate_shape2d_feature_values(std::vector>& f circle.calculate(roidata, s); circle.save_value(roidata.fvals); + GeodeticLengthThicknessFeature geodetic; + geodetic.calculate(roidata, s); + geodetic.save_value(roidata.fvals); + + ErosionPixelsFeature erosion; + erosion.calculate(roidata, s); + erosion.save_value(roidata.fvals); + fvals = roidata.fvals; } @@ -156,6 +169,26 @@ static void assert_shape2d_feature( ASSERT_TRUE(agrees_gt(fvals[static_cast(feature)][0], shape2d_truth[feature_name], frac_tolerance)); } +static void assert_unvetted_no_direct_oracle_shape2d_feature( + const std::vector>& fvals, + Nyxus::Feature2D feature, + const std::string& feature_name, + double frac_tolerance = 1000.0) +{ + SCOPED_TRACE(std::string("UNVETTED_NO_DIRECT_ORACLE__") + feature_name); + assert_shape2d_feature(fvals, feature, feature_name, frac_tolerance); +} + +static void assert_verifiable_with_3p_builtin_oracle_shape2d_feature( + const std::vector>& fvals, + Nyxus::Feature2D feature, + const std::string& feature_name, + double frac_tolerance = 1000.0) +{ + SCOPED_TRACE(std::string("VERIFIABLE_WITH_3P_BUILTIN_ORACLE__") + feature_name); + assert_shape2d_feature(fvals, feature, feature_name, frac_tolerance); +} + void test_shape2d_basic_morphology_features() { std::vector> fvals; @@ -197,7 +230,6 @@ void test_shape2d_contour_features() calculate_shape2d_feature_values(fvals); assert_shape2d_feature(fvals, Nyxus::Feature2D::PERIMETER, "PERIMETER"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::DIAMETER_EQUAL_PERIMETER, "DIAMETER_EQUAL_PERIMETER"); assert_shape2d_feature(fvals, Nyxus::Feature2D::EDGE_MEAN_INTENSITY, "EDGE_MEAN_INTENSITY"); assert_shape2d_feature(fvals, Nyxus::Feature2D::EDGE_STDDEV_INTENSITY, "EDGE_STDDEV_INTENSITY"); assert_shape2d_feature(fvals, Nyxus::Feature2D::EDGE_MAX_INTENSITY, "EDGE_MAX_INTENSITY"); @@ -205,6 +237,14 @@ void test_shape2d_contour_features() assert_shape2d_feature(fvals, Nyxus::Feature2D::EDGE_INTEGRATED_INTENSITY, "EDGE_INTEGRATED_INTENSITY"); } +void test_shape2d_verifiable_with_3p_builtin_oracle_contour_diameter_equal_perimeter() +{ + std::vector> fvals; + calculate_shape2d_feature_values(fvals); + + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::DIAMETER_EQUAL_PERIMETER, "DIAMETER_EQUAL_PERIMETER"); +} + void test_shape2d_convex_hull_features() { std::vector> fvals; @@ -215,27 +255,27 @@ void test_shape2d_convex_hull_features() assert_shape2d_feature(fvals, Nyxus::Feature2D::SOLIDITY, "SOLIDITY"); } -void test_shape2d_extrema_features() +void test_shape2d_verifiable_with_3p_builtin_oracle_extrema_features() { std::vector> fvals; calculate_shape2d_feature_values(fvals); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P1_X, "EXTREMA_P1_X"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P1_Y, "EXTREMA_P1_Y"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P2_X, "EXTREMA_P2_X"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P2_Y, "EXTREMA_P2_Y"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P3_X, "EXTREMA_P3_X"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P3_Y, "EXTREMA_P3_Y"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P4_X, "EXTREMA_P4_X"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P4_Y, "EXTREMA_P4_Y"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P5_X, "EXTREMA_P5_X"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P5_Y, "EXTREMA_P5_Y"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P6_X, "EXTREMA_P6_X"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P6_Y, "EXTREMA_P6_Y"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P7_X, "EXTREMA_P7_X"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P7_Y, "EXTREMA_P7_Y"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P8_X, "EXTREMA_P8_X"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P8_Y, "EXTREMA_P8_Y"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P1_X, "EXTREMA_P1_X"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P1_Y, "EXTREMA_P1_Y"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P2_X, "EXTREMA_P2_X"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P2_Y, "EXTREMA_P2_Y"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P3_X, "EXTREMA_P3_X"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P3_Y, "EXTREMA_P3_Y"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P4_X, "EXTREMA_P4_X"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P4_Y, "EXTREMA_P4_Y"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P5_X, "EXTREMA_P5_X"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P5_Y, "EXTREMA_P5_Y"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P6_X, "EXTREMA_P6_X"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P6_Y, "EXTREMA_P6_Y"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P7_X, "EXTREMA_P7_X"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P7_Y, "EXTREMA_P7_Y"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P8_X, "EXTREMA_P8_X"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::EXTREMA_P8_Y, "EXTREMA_P8_Y"); } void test_shape2d_misc_shape_features() @@ -244,12 +284,35 @@ void test_shape2d_misc_shape_features() calculate_shape2d_feature_values(fvals); assert_shape2d_feature(fvals, Nyxus::Feature2D::EULER_NUMBER, "EULER_NUMBER"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::FRACT_DIM_BOXCOUNT, "FRACT_DIM_BOXCOUNT"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::FRACT_DIM_PERIMETER, "FRACT_DIM_PERIMETER"); assert_shape2d_feature(fvals, Nyxus::Feature2D::DIAMETER_MIN_ENCLOSING_CIRCLE, "DIAMETER_MIN_ENCLOSING_CIRCLE"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::DIAMETER_CIRCUMSCRIBING_CIRCLE, "DIAMETER_CIRCUMSCRIBING_CIRCLE"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::DIAMETER_INSCRIBING_CIRCLE, "DIAMETER_INSCRIBING_CIRCLE"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::ROI_RADIUS_MEAN, "ROI_RADIUS_MEAN"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::ROI_RADIUS_MAX, "ROI_RADIUS_MAX"); - assert_shape2d_feature(fvals, Nyxus::Feature2D::ROI_RADIUS_MEDIAN, "ROI_RADIUS_MEDIAN"); +} + +void test_shape2d_verifiable_with_3p_builtin_oracle_fractal_circle_features() +{ + std::vector> fvals; + calculate_shape2d_feature_values(fvals); + + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::FRACT_DIM_BOXCOUNT, "FRACT_DIM_BOXCOUNT"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::FRACT_DIM_PERIMETER, "FRACT_DIM_PERIMETER"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::DIAMETER_CIRCUMSCRIBING_CIRCLE, "DIAMETER_CIRCUMSCRIBING_CIRCLE"); + assert_verifiable_with_3p_builtin_oracle_shape2d_feature(fvals, Nyxus::Feature2D::DIAMETER_INSCRIBING_CIRCLE, "DIAMETER_INSCRIBING_CIRCLE"); +} + +void test_shape2d_unvetted_no_direct_oracle_radius_features() +{ + std::vector> fvals; + calculate_shape2d_feature_values(fvals); + + assert_unvetted_no_direct_oracle_shape2d_feature(fvals, Nyxus::Feature2D::ROI_RADIUS_MEAN, "ROI_RADIUS_MEAN"); + assert_unvetted_no_direct_oracle_shape2d_feature(fvals, Nyxus::Feature2D::ROI_RADIUS_MAX, "ROI_RADIUS_MAX"); + assert_unvetted_no_direct_oracle_shape2d_feature(fvals, Nyxus::Feature2D::ROI_RADIUS_MEDIAN, "ROI_RADIUS_MEDIAN"); +} + +void test_shape2d_verifiable_with_3p_builtin_oracle_geodetic_thickness_erosion_features() +{ + std::vector> fvals; + calculate_shape2d_feature_values(fvals); + 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"); }