Skip to content

Commit

Permalink
ENH: Add multi component support to MultiThresholdObjectsFilter (#1184)
Browse files Browse the repository at this point in the history
* Added component index to ArrayThreshold

Signed-off-by: Jared Duffey <[email protected]>

* Added multi-component support to MultiThresholdObjectsFilter

Signed-off-by: Jared Duffey <[email protected]>

* Updated multi-component test

Signed-off-by: Jared Duffey <[email protected]>

---------

Signed-off-by: Jared Duffey <[email protected]>
  • Loading branch information
JDuffeyBQ authored Jan 24, 2025
1 parent 6eac7f1 commit 32837a3
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 161 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ class SIMPLNXCORE_EXPORT MultiThresholdObjectsFilter : public IFilter

enum ErrorCodes : int64
{
PathNotFoundError = -178,
NonScalarArrayFound = -4001,
UnequalComponents = -4001,
UnequalTuples = -4002,
CustomTrueWithBoolean = -4003,
CustomFalseWithBoolean = -4004,
CustomTrueOutOfBounds = -4005,
CustomFalseOutOfBounds = -4006
CustomFalseOutOfBounds = -4006,
InvalidComponentIndex = -4007
};

/**
Expand Down
91 changes: 83 additions & 8 deletions src/Plugins/SimplnxCore/test/MultiThresholdObjectsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ namespace
const std::string k_TestArrayFloatName = "TestArrayFloat";
const std::string k_TestArrayIntName = "TestArrayInt";
const std::string k_ThresholdArrayName = "ThresholdArray";
const std::string k_MultiComponentArrayName = "MultiComponent";

const DataPath k_ImageCellDataName({k_ImageGeometry, k_CellData});
const DataPath k_TestArrayFloatPath = k_ImageCellDataName.createChildPath(k_TestArrayFloatName);
const DataPath k_TestArrayIntPath = k_ImageCellDataName.createChildPath(k_TestArrayIntName);
const DataPath k_MultiComponentArrayPath = k_ImageCellDataName.createChildPath(k_MultiComponentArrayName);
const DataPath k_ThresholdArrayPath = k_ImageCellDataName.createChildPath(k_ThresholdArrayName);

const DataPath k_MultiComponentArrayPath = k_ImageCellDataName.createChildPath("MultiComponentArray");
const DataPath k_MismatchingComponentsArrayPath = k_ImageCellDataName.createChildPath("MismatchingComponentsArray");
const DataPath k_MismatchingTuplesArrayPath({"MismatchingTuplesArray"});

DataStructure CreateTestDataStructure()
Expand All @@ -34,24 +36,34 @@ DataStructure CreateTestDataStructure()

std::vector<usize> tDims = {20};
std::vector<usize> cDims = {1};
std::vector<usize> cDimsMulti = {3};
float fnum = 0.0f;
int inum = 0;
AttributeMatrix* am = AttributeMatrix::Create(dataStructure, k_CellData, tDims, image->getId());
Float32Array* data = Float32Array::CreateWithStore<Float32DataStore>(dataStructure, k_TestArrayFloatName, tDims, cDims, am->getId());
Int32Array* data1 = Int32Array::CreateWithStore<Int32DataStore>(dataStructure, k_TestArrayIntName, tDims, cDims, am->getId());
Int32Array* multiComponentData = Int32Array::CreateWithStore<Int32DataStore>(dataStructure, k_MultiComponentArrayName, tDims, cDimsMulti, am->getId());

Float32Array* invalid1 = Float32Array::CreateWithStore<Float32DataStore>(dataStructure, k_MultiComponentArrayPath.getTargetName(), tDims, std::vector<usize>{3}, am->getId());
Float32Array* invalid1 = Float32Array::CreateWithStore<Float32DataStore>(dataStructure, k_MismatchingComponentsArrayPath.getTargetName(), tDims, cDimsMulti, am->getId());
invalid1->fill(1.0);
Float32Array* invalid2 = Float32Array::CreateWithStore<Float32DataStore>(dataStructure, k_MismatchingTuplesArrayPath.getTargetName(), std::vector<usize>{10}, cDims);
invalid2->fill(2.0);

usize numComponents = multiComponentData->getNumberOfComponents();
int32 sign = 1;

// Fill the float array with {.01,.02,.03,.04,.05,.06,.07,.08,.09,.10,.11,.12,.13,.14,.15.,16,.17,.18,.19,.20}
// Fill the int array with { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 }
// Fill multi-component array with {{0, 0, 0}, {1, -1, 1}, {-2, 2, -2}, ..., {17, -17, 17}, {-18, 18, -18}, {19, -19, 19}}
for(usize i = 0; i < 20; i++)
{
fnum += 0.01f;
(*data)[i] = fnum; // float array
(*data1)[i] = inum; // int array
multiComponentData->setComponent(i, 0, i * -sign);
multiComponentData->setComponent(i, 1, i * sign);
multiComponentData->setComponent(i, 2, i * -sign);
sign *= -1;
++inum;
}
return dataStructure;
Expand Down Expand Up @@ -221,13 +233,13 @@ TEST_CASE("SimplnxCore::MultiThresholdObjects: Invalid Execution", "[SimplnxCore
MultiThresholdObjectsFilter filter;
DataStructure dataStructure = CreateTestDataStructure();
Arguments args;
args.insertOrAssign(MultiThresholdObjectsFilter::k_CreatedDataName_Key, std::make_any<std::string>(k_ThresholdArrayName));

SECTION("Empty ArrayThresholdSet")
{
ArrayThresholdSet thresholdSet;

args.insertOrAssign(MultiThresholdObjectsFilter::k_ArrayThresholdsObject_Key, std::make_any<ArrayThresholdSet>(thresholdSet));
args.insertOrAssign(MultiThresholdObjectsFilter::k_CreatedDataName_Key, std::make_any<std::string>(k_ThresholdArrayName));
}
SECTION("Empty ArrayThreshold DataPath")
{
Expand All @@ -238,19 +250,33 @@ TEST_CASE("SimplnxCore::MultiThresholdObjects: Invalid Execution", "[SimplnxCore
thresholdSet.setArrayThresholds({threshold});

args.insertOrAssign(MultiThresholdObjectsFilter::k_ArrayThresholdsObject_Key, std::make_any<ArrayThresholdSet>(thresholdSet));
args.insertOrAssign(MultiThresholdObjectsFilter::k_CreatedDataName_Key, std::make_any<std::string>(k_ThresholdArrayName));
}
SECTION("MultiComponents in Threshold Array")
SECTION("Mismatching Components in Threshold Arrays")
{
ArrayThresholdSet thresholdSet;
auto threshold1 = std::make_shared<ArrayThreshold>();
threshold1->setArrayPath(k_TestArrayFloatPath);
threshold1->setComparisonType(ArrayThreshold::ComparisonType::GreaterThan);
threshold1->setComparisonValue(0.1);
auto threshold2 = std::make_shared<ArrayThreshold>();
threshold2->setArrayPath(k_MismatchingComponentsArrayPath);
threshold2->setComparisonType(ArrayThreshold::ComparisonType::GreaterThan);
threshold2->setComparisonValue(0.1);
thresholdSet.setArrayThresholds({threshold1, threshold2});

args.insertOrAssign(MultiThresholdObjectsFilter::k_ArrayThresholdsObject_Key, std::make_any<ArrayThresholdSet>(thresholdSet));
}
SECTION("Out of Bounds Component Index")
{
ArrayThresholdSet thresholdSet;
auto threshold = std::make_shared<ArrayThreshold>();
threshold->setArrayPath(k_MultiComponentArrayPath);
threshold->setArrayPath(k_TestArrayFloatPath);
threshold->setComparisonType(ArrayThreshold::ComparisonType::GreaterThan);
threshold->setComparisonValue(0.1);
threshold->setComponentIndex(1);
thresholdSet.setArrayThresholds({threshold});

args.insertOrAssign(MultiThresholdObjectsFilter::k_ArrayThresholdsObject_Key, std::make_any<ArrayThresholdSet>(thresholdSet));
args.insertOrAssign(MultiThresholdObjectsFilter::k_CreatedDataName_Key, std::make_any<std::string>(k_ThresholdArrayName));
}
SECTION("Mismatching Tuples in Threshold Arrays")
{
Expand All @@ -266,7 +292,6 @@ TEST_CASE("SimplnxCore::MultiThresholdObjects: Invalid Execution", "[SimplnxCore
thresholdSet.setArrayThresholds({threshold1, threshold2});

args.insertOrAssign(MultiThresholdObjectsFilter::k_ArrayThresholdsObject_Key, std::make_any<ArrayThresholdSet>(thresholdSet));
args.insertOrAssign(MultiThresholdObjectsFilter::k_CreatedDataName_Key, std::make_any<std::string>(k_ThresholdArrayName));
}

// Preflight the filter and check result
Expand Down Expand Up @@ -676,3 +701,53 @@ TEST_CASE("SimplnxCore::MultiThresholdObjects: Valid Execution, DataType", "[Sim
checkMaskValues<float64>(dataStructure, k_ThresholdArrayPath);
}
}

TEST_CASE("SimplnxCore::MultiThresholdObjects: Valid Execution - Multicomponent", "[SimplnxCore][MultiThresholdObjects]")
{
DataStructure dataStructure = CreateTestDataStructure();

MultiThresholdObjectsFilter filter;
Arguments args;

ArrayThresholdSet thresholdSet;
auto threshold = std::make_shared<ArrayThreshold>();
threshold->setArrayPath(k_MultiComponentArrayPath);
threshold->setComparisonType(ArrayThreshold::ComparisonType::GreaterThan);
threshold->setComparisonValue(0);
threshold->setComponentIndex(1);
thresholdSet.setArrayThresholds({threshold});

args.insertOrAssign(MultiThresholdObjectsFilter::k_ArrayThresholdsObject_Key, std::make_any<ArrayThresholdSet>(thresholdSet));
args.insertOrAssign(MultiThresholdObjectsFilter::k_CreatedDataName_Key, std::make_any<std::string>(k_ThresholdArrayName));
args.insertOrAssign(MultiThresholdObjectsFilter::k_CreatedMaskType_Key, std::make_any<DataType>(DataType::boolean));

// Preflight the filter and check result
auto preflightResult = filter.preflight(dataStructure, args);
SIMPLNX_RESULT_REQUIRE_VALID(preflightResult.outputActions)

// Execute the filter and check the result
auto executeResult = filter.execute(dataStructure, args);
SIMPLNX_RESULT_REQUIRE_VALID(executeResult.result)

auto* thresholdArray = dataStructure.getDataAs<BoolArray>(k_ThresholdArrayPath);
REQUIRE(thresholdArray != nullptr);

usize numTuples = thresholdArray->getNumberOfTuples();

// (x, y, z)
// y > 0
// even tuple indices should be true except 0
REQUIRE_FALSE((*thresholdArray)[0]);
for(usize i = 1; i < numTuples; i++)
{
bool value = (*thresholdArray)[i];
if(i % 2 == 0)
{
REQUIRE(value);
}
else
{
REQUIRE_FALSE(value);
}
}
}
1 change: 1 addition & 0 deletions src/Plugins/SimplnxCore/wrapping/python/simplnxpy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@ PYBIND11_MODULE(simplnx, mod)
arrayThreshold.def_property("array_path", &ArrayThreshold::getArrayPath, &ArrayThreshold::setArrayPath);
arrayThreshold.def_property("value", &ArrayThreshold::getComparisonValue, &ArrayThreshold::setComparisonValue);
arrayThreshold.def_property("comparison", &ArrayThreshold::getComparisonType, &ArrayThreshold::setComparisonType);
arrayThreshold.def_property("component_index", &ArrayThreshold::getComponentIndex, &ArrayThreshold::setComponentIndex);

py::class_<ArrayThresholdSet, IArrayThreshold, std::shared_ptr<ArrayThresholdSet>> arrayThresholdSet(mod, "ArrayThresholdSet");
arrayThresholdSet.def(py::init<>());
Expand Down
2 changes: 1 addition & 1 deletion src/simplnx/Parameters/ArrayThresholdsParameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ IParameter::AcceptedTypes ArrayThresholdsParameter::acceptedTypes() const
//------------------------------------------------------------------------------
IParameter::VersionType ArrayThresholdsParameter::getVersion() const
{
return 1;
return 2;
}

nlohmann::json ArrayThresholdsParameter::toJsonImpl(const std::any& value) const
Expand Down
14 changes: 14 additions & 0 deletions src/simplnx/Utilities/ArrayThreshold.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ constexpr StringLiteral k_Inverted_Tag = "inverted";
constexpr StringLiteral k_Union_Tag = "union";
constexpr StringLiteral k_Value_Tag = "value";
constexpr StringLiteral k_ArrayPath_Tag = "array_path";
constexpr StringLiteral k_ComponentIndex_Tag = "component_index";
constexpr StringLiteral k_Comparison_Tag = "comparison";
constexpr StringLiteral k_Thresholds_Tag = "thresholds";

Expand Down Expand Up @@ -114,6 +115,16 @@ void ArrayThreshold::setComparisonValue(ComparisonValue value)
m_Value = value;
}

usize ArrayThreshold::getComponentIndex() const
{
return m_ComponentIndex;
}

void ArrayThreshold::setComponentIndex(usize index)
{
m_ComponentIndex = index;
}

ArrayThreshold::ComparisonType ArrayThreshold::getComparisonType() const
{
return m_Comparison;
Expand All @@ -133,6 +144,7 @@ nlohmann::json ArrayThreshold::toJson() const
auto json = IArrayThreshold::toJson();
json[k_Type_Tag] = k_ArrayType;
json[k_ArrayPath_Tag] = getArrayPath().toString();
json[k_ComponentIndex_Tag] = getComponentIndex();
json[k_Value_Tag] = getComparisonValue();
json[k_Comparison_Tag] = getComparisonType();

Expand All @@ -157,6 +169,8 @@ std::shared_ptr<ArrayThreshold> ArrayThreshold::FromJson(const nlohmann::json& j
return nullptr;
}
threshold->setArrayPath(arrayPath.value());
usize componentIndex = json.contains(k_ComponentIndex_Tag) ? json[k_ComponentIndex_Tag].get<usize>() : 0;
threshold->setComponentIndex(componentIndex);
threshold->setComparisonType(static_cast<ComparisonType>(json[k_Comparison_Tag].get<int32>()));
threshold->setComparisonValue(json[k_Value_Tag].get<ComparisonValue>());

Expand Down
4 changes: 4 additions & 0 deletions src/simplnx/Utilities/ArrayThreshold.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ class SIMPLNX_EXPORT ArrayThreshold : public IArrayThreshold
[[nodiscard]] ComparisonValue getComparisonValue() const;
void setComparisonValue(ComparisonValue value);

[[nodiscard]] usize getComponentIndex() const;
void setComponentIndex(usize index);

[[nodiscard]] ComparisonType getComparisonType() const;
void setComparisonType(ComparisonType comparison);

Expand All @@ -86,6 +89,7 @@ class SIMPLNX_EXPORT ArrayThreshold : public IArrayThreshold
private:
DataPath m_ArrayPath;
ComparisonValue m_Value{0.0};
usize m_ComponentIndex = 0;
ComparisonType m_Comparison{ComparisonType::GreaterThan};
};

Expand Down

0 comments on commit 32837a3

Please sign in to comment.