diff --git a/src/Plugins/ComplexCore/docs/FindArrayStatisticsFilter.md b/src/Plugins/ComplexCore/docs/FindArrayStatisticsFilter.md index aa5ae0cecd..5ec29c292b 100644 --- a/src/Plugins/ComplexCore/docs/FindArrayStatisticsFilter.md +++ b/src/Plugins/ComplexCore/docs/FindArrayStatisticsFilter.md @@ -69,21 +69,22 @@ None ## Created Objects ## -| Kind | Default Name | Type | Component Dimensions | Description | -|---------------------|-------------------------|-----------------------------------|----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **Attribute Array** | Feature-Has-Data | bool | (1) | Indicates, for each feature, whether or not the feature actually contains any data (only usable when *Compute Statistics Per Feature/Ensemble* is turned on). This array is especially useful to help determine whether or not the outputted statistics are actually valid or not for a given feature. | -| **Attribute Array** | Histogram | uint64 | (Number of Bins) | Histogram of the input array, if _Find Histogram_ is checked | -| **Attribute Array** | Most Populated Bin | uint64 | (2) | Most populated bin from the histogram of the input array, if _Find Histogram_ is checked. First component is the bin index (0-based), second component is the number of values in the bin. | -| **Attribute Array** | Length | int64_t | (1) | Length of the input array, if _Find Length_ is checked | -| **Attribute Array** | Minimum | same as input **Attribute Array** | (1) | Minimum of the input array, if _Find Minimum_ is checked | -| **Attribute Array** | Maximum | same as input **Attribute Array** | (1) | Maximum of the input array, if _Find Maximum_ is checked | -| **Attribute Array** | Mean | double | (1) | Arithmetic mean of the input array, if _Find Mean_ is checked | -| **Attribute Array** | Median | double | (1) | Median of the input array, if _Find Median_ is checked | -| **Neighbor List** | Mode | same as input **Attribute Array** | (1) | Modes of the input array, if _Find Mode_ is checked | -| **Attribute Array** | Standard Deviation | double | (1) | Standard deviation of the input array, if _Find Standard Deviation_ is checked | -| **Attribute Array** | Summation | double | (1) | Summation of the input array, if _Find Summation_ is checked | -| **Attribute Array** | Standardized | double | (1) | Standardized version of the input array, if _Standardize Data_ is checked | -| **Attribute Array** | Number of Unique Values | int32_t | (1) | The number of unique values in the input array, if _Find Number of Unique Values_ is checked | +| Kind | Default Name | Type | Component Dimensions | Description | +|---------------------|----------------------------|---------------------------------|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Attribute Array** | Feature-Has-Data | bool | (1) | Indicates, for each feature, whether or not the feature actually contains any data (only usable when *Compute Statistics Per Feature/Ensemble* is turned on). This array is especially useful to help determine whether or not the outputted statistics are actually valid or not for a given feature. | +| **Attribute Array** | Histogram | uint64 | (Number of Bins) | Histogram of the input array, if _Find Histogram_ is checked | +| **Attribute Array** | Most Populated Bin | uint64 | (2) | Most populated bin from the histogram of the input array, if _Find Histogram_ is checked. First component is the bin index (0-based), second component is the number of values in the bin. | +| **Neighbor List** | Modal Histogram Bin Ranges | float | (1) | Ranges, in physical units, of histogram bin(s) that contain mode value(s). _Find Histogram_, _Find Modal Histogram Bin Ranges_, and _Find Mode_ must all be checked. The min/max values are stored in the neighbor list arrays from bin 0 - bin N (Example: [bin0min, bin0max, bin1min, bin1max, ... binNmin, binNmax]) | +| **Attribute Array** | Length | int64_t | (1) | Length of the input array, if _Find Length_ is checked | +| **Attribute Array** | Minimum | same as input **Attribute Array** | (1) | Minimum of the input array, if _Find Minimum_ is checked | +| **Attribute Array** | Maximum | same as input **Attribute Array** | (1) | Maximum of the input array, if _Find Maximum_ is checked | +| **Attribute Array** | Mean | double | (1) | Arithmetic mean of the input array, if _Find Mean_ is checked | +| **Attribute Array** | Median | double | (1) | Median of the input array, if _Find Median_ is checked | +| **Neighbor List** | Mode | same as input **Attribute Array** | (1) | Modes of the input array, if _Find Mode_ is checked | +| **Attribute Array** | Standard Deviation | double | (1) | Standard deviation of the input array, if _Find Standard Deviation_ is checked | +| **Attribute Array** | Summation | double | (1) | Summation of the input array, if _Find Summation_ is checked | +| **Attribute Array** | Standardized | double | (1) | Standardized version of the input array, if _Standardize Data_ is checked | +| **Attribute Array** | Number of Unique Values | int32_t | (1) | The number of unique values in the input array, if _Find Number of Unique Values_ is checked | ## Example Pipelines ## diff --git a/src/Plugins/ComplexCore/src/ComplexCore/Filters/Algorithms/FindArrayStatistics.cpp b/src/Plugins/ComplexCore/src/ComplexCore/Filters/Algorithms/FindArrayStatistics.cpp index 00fdd65bbe..56bdd1b080 100644 --- a/src/Plugins/ComplexCore/src/ComplexCore/Filters/Algorithms/FindArrayStatistics.cpp +++ b/src/Plugins/ComplexCore/src/ComplexCore/Filters/Algorithms/FindArrayStatistics.cpp @@ -17,9 +17,9 @@ class FindArrayStatisticsByIndexImpl { public: FindArrayStatisticsByIndexImpl(bool length, bool min, bool max, bool mean, bool mode, bool stdDeviation, bool summation, bool hist, float64 histmin, float64 histmax, bool histfullrange, - int32 numBins, const std::unique_ptr& mask, const Int32Array* featureIds, const DataArray& source, BoolArray* featureHasDataArray, + int32 numBins, bool modalBinRanges, const std::unique_ptr& mask, const Int32Array* featureIds, const DataArray& source, BoolArray* featureHasDataArray, UInt64Array* lengthArray, DataArray* minArray, DataArray* maxArray, Float32Array* meanArray, NeighborList* modeArray, Float32Array* stdDevArray, - Float32Array* summationArray, UInt64Array* histArray, UInt64Array* mostPopulatedBinArray, FindArrayStatistics* filter) + Float32Array* summationArray, UInt64Array* histArray, UInt64Array* mostPopulatedBinArray, NeighborList* modalBinRangesArray, FindArrayStatistics* filter) : m_Length(length) , m_Min(min) , m_Max(max) @@ -32,6 +32,7 @@ class FindArrayStatisticsByIndexImpl , m_HistMax(histmax) , m_HistFullRange(histfullrange) , m_NumBins(numBins) + , m_ModalBinRanges(modalBinRanges) , m_Mask(mask) , m_FeatureIds(featureIds) , m_Source(source) @@ -45,6 +46,7 @@ class FindArrayStatisticsByIndexImpl , m_SummationArray(summationArray) , m_HistArray(histArray) , m_MostPopulatedBinArray(mostPopulatedBinArray) + , m_ModalBinRangesArray(modalBinRangesArray) , m_Filter(filter) { } @@ -252,7 +254,39 @@ class FindArrayStatisticsByIndexImpl } } // end of numTuples loop } // end of increment else - } // end of length if + + if(m_ModalBinRanges) + { + if(std::fabs(increment) < 1E-10) + { + m_ModalBinRangesArray->addEntry(j, histMin); + m_ModalBinRangesArray->addEntry(j, histMax); + } + else + { + auto modeList = m_ModeArray->getList(j); + for(int i = 0; i < modeList->size(); i++) + { + const float32 mode = modeList->at(i); + const auto modalBin = static_cast((mode - histMin) / increment); + float32 minBinValue = 0.0f; + float32 maxBinValue = 0.0f; + if((modalBin >= 0) && (modalBin < m_NumBins)) // make certain bin is in range + { + minBinValue = static_cast(histMin + (modalBin * increment)); + maxBinValue = static_cast(histMin + ((modalBin + 1) * increment)); + } + else if(mode == histMax) + { + minBinValue = static_cast(histMin + ((modalBin - 1) * increment)); + maxBinValue = static_cast(histMin + (modalBin * increment)); + } + m_ModalBinRangesArray->addEntry(j, minBinValue); + m_ModalBinRangesArray->addEntry(j, maxBinValue); + } + } + } + } // end of length if histDataStorePtr->setTuple(j, histogram); @@ -335,6 +369,7 @@ class FindArrayStatisticsByIndexImpl bool m_StdDeviation; bool m_Summation; bool m_Histogram; + bool m_ModalBinRanges; float64 m_HistMin; float64 m_HistMax; bool m_HistFullRange; @@ -352,6 +387,7 @@ class FindArrayStatisticsByIndexImpl Float32Array* m_SummationArray = nullptr; UInt64Array* m_HistArray = nullptr; UInt64Array* m_MostPopulatedBinArray = nullptr; + NeighborList* m_ModalBinRangesArray = nullptr; FindArrayStatistics* m_Filter = nullptr; }; @@ -564,6 +600,28 @@ void FindStatisticsImpl(const ContainerType& data, std::vector& arrays, arr10DataStorePtr->setComponent(0, 0, index); arr10DataStorePtr->setComponent(0, 1, values[index]); } + + if(inputValues->FindModalBinRanges) + { + auto* array5Ptr = dynamic_cast*>(arrays[5]); + if(array5Ptr == nullptr) + { + throw std::invalid_argument("findStatisticsImpl() could not dynamic_cast 'Mode' array to needed type. Check input array selection."); + } + + auto* array11Ptr = dynamic_cast*>(arrays[11]); + if(array11Ptr == nullptr) + { + throw std::invalid_argument("findStatisticsImpl() could not dynamic_cast 'Modal Bin Ranges' array to needed type. Check input array selection."); + } + + for(const T& mode : array5Ptr->at(0)) + { + std::pair range = StatisticsCalculations::findModalBinRange(data, inputValues->MinRange, inputValues->MaxRange, inputValues->UseFullRange, inputValues->NumBins, mode); + array11Ptr->addEntry(0, range.first); + array11Ptr->addEntry(0, range.second); + } + } } if(inputValues->FindNumUniqueValues) @@ -594,7 +652,8 @@ void FindStatistics(const DataArray& source, const Int32Array* featureIds, co auto* summationArrayPtr = dynamic_cast(arrays[7]); auto* histArrayPtr = dynamic_cast(arrays[8]); auto* mostPopulatedBinPtr = dynamic_cast(arrays[10]); - auto* featureHasDataPtr = dynamic_cast(arrays[11]); + auto* modalBinsArrayPtr = dynamic_cast*>(arrays[11]); + auto* featureHasDataPtr = dynamic_cast(arrays[12]); #ifdef COMPLEX_ENABLE_MULTICORE const tbb::simple_partitioner simplePartitioner; @@ -603,8 +662,9 @@ void FindStatistics(const DataArray& source, const Int32Array* featureIds, co tbb::parallel_for(tbbRange, FindArrayStatisticsByIndexImpl(inputValues->FindLength, inputValues->FindMin, inputValues->FindMax, inputValues->FindMean, inputValues->FindMode, inputValues->FindStdDeviation, inputValues->FindSummation, inputValues->FindHistogram, inputValues->MinRange, inputValues->MaxRange, - inputValues->UseFullRange, inputValues->NumBins, mask, featureIds, source, featureHasDataPtr, lengthArrayPtr, minArrayPtr, maxArrayPtr, - meanArrayPtr, modeArrayPtr, stdDevArrayPtr, summationArrayPtr, histArrayPtr, mostPopulatedBinPtr, filter), + inputValues->UseFullRange, inputValues->NumBins, inputValues->FindModalBinRanges, mask, featureIds, source, featureHasDataPtr, lengthArrayPtr, + minArrayPtr, maxArrayPtr, meanArrayPtr, modeArrayPtr, stdDevArrayPtr, summationArrayPtr, histArrayPtr, mostPopulatedBinPtr, modalBinsArrayPtr, + filter), simplePartitioner); #else auto impl = FindArrayStatisticsByIndexImpl(inputValues->FindLength, inputValues->FindMin, inputValues->FindMax, inputValues->FindMean, inputValues->FindMode, inputValues->FindStdDeviation, @@ -879,7 +939,7 @@ Result<> FindArrayStatistics::operator()() return {}; } - std::vector arrays(11, nullptr); + std::vector arrays(12, nullptr); if(m_InputValues->FindLength) { @@ -918,6 +978,10 @@ Result<> FindArrayStatistics::operator()() arrays[8] = m_DataStructure.getDataAs(m_InputValues->HistogramArrayName); arrays[10] = m_DataStructure.getDataAs(m_InputValues->MostPopulatedBinArrayName); } + if(m_InputValues->FindModalBinRanges) + { + arrays[11] = m_DataStructure.getDataAs(m_InputValues->ModalBinArrayName); + } if(m_InputValues->FindNumUniqueValues) { arrays[9] = m_DataStructure.getDataAs(m_InputValues->NumUniqueValuesName); @@ -926,8 +990,8 @@ Result<> FindArrayStatistics::operator()() usize numFeatures = 0; if(m_InputValues->ComputeByIndex) { - arrays.resize(12); - arrays[11] = m_DataStructure.getDataAs(m_InputValues->FeatureHasDataArrayName); + arrays.resize(13); + arrays[12] = m_DataStructure.getDataAs(m_InputValues->FeatureHasDataArrayName); const auto& featureIds = m_DataStructure.getDataRefAs(m_InputValues->FeatureIdsArrayPath); numFeatures = findNumFeatures(featureIds); diff --git a/src/Plugins/ComplexCore/src/ComplexCore/Filters/Algorithms/FindArrayStatistics.hpp b/src/Plugins/ComplexCore/src/ComplexCore/Filters/Algorithms/FindArrayStatistics.hpp index c25b006070..c4574b5471 100644 --- a/src/Plugins/ComplexCore/src/ComplexCore/Filters/Algorithms/FindArrayStatistics.hpp +++ b/src/Plugins/ComplexCore/src/ComplexCore/Filters/Algorithms/FindArrayStatistics.hpp @@ -26,6 +26,7 @@ struct COMPLEXCORE_EXPORT FindArrayStatisticsInputValues bool FindMean; bool FindMedian; bool FindMode; + bool FindModalBinRanges; bool FindStdDeviation; bool FindSummation; bool UseMask; @@ -38,6 +39,7 @@ struct COMPLEXCORE_EXPORT FindArrayStatisticsInputValues DataPath DestinationAttributeMatrix; DataPath HistogramArrayName; DataPath MostPopulatedBinArrayName; + DataPath ModalBinArrayName; DataPath FeatureHasDataArrayName; DataPath LengthArrayName; DataPath MinimumArrayName; diff --git a/src/Plugins/ComplexCore/src/ComplexCore/Filters/FindArrayStatisticsFilter.cpp b/src/Plugins/ComplexCore/src/ComplexCore/Filters/FindArrayStatisticsFilter.cpp index 4c2b845ba1..e13648c64b 100644 --- a/src/Plugins/ComplexCore/src/ComplexCore/Filters/FindArrayStatisticsFilter.cpp +++ b/src/Plugins/ComplexCore/src/ComplexCore/Filters/FindArrayStatisticsFilter.cpp @@ -37,6 +37,7 @@ OutputActions CreateCompatibleArrays(const DataStructure& data, const Arguments& auto findMean = args.value(FindArrayStatisticsFilter::k_FindMean_Key); auto findMedian = args.value(FindArrayStatisticsFilter::k_FindMedian_Key); auto findMode = args.value(FindArrayStatisticsFilter::k_FindMode_Key); + auto findModalBinRanges = args.value(FindArrayStatisticsFilter::k_FindModalBinRanges_Key); auto findStdDeviation = args.value(FindArrayStatisticsFilter::k_FindStdDeviation_Key); auto findSummation = args.value(FindArrayStatisticsFilter::k_FindSummation_Key); auto findHistogramValue = args.value(FindArrayStatisticsFilter::k_FindHistogram_Key); @@ -122,6 +123,12 @@ OutputActions CreateCompatibleArrays(const DataStructure& data, const Arguments& auto action = std::make_unique(DataType::uint64, tupleDims, std::vector{2}, destinationAttributeMatrixValue.createChildPath(arrayPath)); actions.appendAction(std::move(action)); } + if(findModalBinRanges) + { + auto arrayPath = args.value(FindArrayStatisticsFilter::k_ModalBinArrayName_Key); + auto action = std::make_unique(DataType::float32, tupleSize, destinationAttributeMatrixValue.createChildPath(arrayPath)); + actions.appendAction(std::move(action)); + } } if(standardizeDataValue) { @@ -195,6 +202,10 @@ Parameters FindArrayStatisticsFilter::parameters() const params.insert(std::make_unique(k_NumBins_Key, "Number of Bins", "Number of bins in histogram", 1)); params.insert(std::make_unique(k_HistogramArrayName_Key, "Histogram Array Name", "The name of the histogram array", "Histogram")); params.insert(std::make_unique(k_MostPopulatedBinArrayName_Key, "Most Populated Bin Array Name", "The name of the Most Populated Bin array", "Most Populated Bin")); + params.insert(std::make_unique(k_FindModalBinRanges_Key, "Find Modal Histogram Bin Ranges", + "Whether to compute the histogram bin ranges that contain the mode values. This option requires that \" Find Mode \" is turned on.", false)); + params.insert(std::make_unique(k_ModalBinArrayName_Key, "Modal Histogram Bin Ranges Array Name", + "The name of the array that stores the histogram bin range(s) that contain the mode(s) of the data.", "Modal Histogram Bin Ranges")); params.insertSeparator(Parameters::Separator{"Optional Data Mask"}); params.insertLinkableParameter( @@ -251,6 +262,8 @@ Parameters FindArrayStatisticsFilter::parameters() const params.linkParameters(k_FindHistogram_Key, k_MinRange_Key, true); params.linkParameters(k_FindHistogram_Key, k_MaxRange_Key, true); params.linkParameters(k_FindHistogram_Key, k_MostPopulatedBinArrayName_Key, true); + params.linkParameters(k_FindHistogram_Key, k_FindModalBinRanges_Key, true); + params.linkParameters(k_FindHistogram_Key, k_ModalBinArrayName_Key, true); params.linkParameters(k_FindLength_Key, k_LengthArrayName_Key, true); params.linkParameters(k_FindMin_Key, k_MinimumArrayName_Key, true); params.linkParameters(k_FindMax_Key, k_MaximumArrayName_Key, true); @@ -286,6 +299,7 @@ IFilter::PreflightResult FindArrayStatisticsFilter::preflightImpl(const DataStru auto pFindMeanValue = filterArgs.value(k_FindMean_Key); auto pFindMedianValue = filterArgs.value(k_FindMedian_Key); auto pFindModeValue = filterArgs.value(k_FindMode_Key); + auto pFindModalBinRanges = filterArgs.value(k_FindModalBinRanges_Key); auto pFindStdDeviationValue = filterArgs.value(k_FindStdDeviation_Key); auto pFindSummationValue = filterArgs.value(k_FindSummation_Key); auto pFindNumUniqueValuesValue = filterArgs.value(k_FindUniqueValues_Key); @@ -365,6 +379,11 @@ IFilter::PreflightResult FindArrayStatisticsFilter::preflightImpl(const DataStru } } + if(pFindHistogramValue && pFindModalBinRanges && !pFindModeValue) + { + return {MakeErrorResult(-57209, fmt::format(R"(To calculate the modal histogram bin ranges, the "Find Mode" option must also be turned on.)")), {}}; + } + if(pFindModeValue && !ExecuteDataFunction(IsIntegerType{}, inputArrayPtr->getDataType())) { std::string msg = "Finding the mode requires selecting an input array with an integer data type (int8, uint8, int16, uint16, int32, uint32, int64, uint64)."; @@ -398,6 +417,7 @@ Result<> FindArrayStatisticsFilter::executeImpl(DataStructure& dataStructure, co inputValues.FindMean = filterArgs.value(k_FindMean_Key); inputValues.FindMedian = filterArgs.value(k_FindMedian_Key); inputValues.FindMode = filterArgs.value(k_FindMode_Key); + inputValues.FindModalBinRanges = filterArgs.value(k_FindModalBinRanges_Key); inputValues.FindStdDeviation = filterArgs.value(k_FindStdDeviation_Key); inputValues.FindSummation = filterArgs.value(k_FindSummation_Key); inputValues.FindNumUniqueValues = filterArgs.value(k_FindUniqueValues_Key); @@ -411,6 +431,7 @@ Result<> FindArrayStatisticsFilter::executeImpl(DataStructure& dataStructure, co inputValues.FeatureHasDataArrayName = inputValues.DestinationAttributeMatrix.createChildPath(filterArgs.value(k_FeatureHasDataArrayName_Key)); inputValues.HistogramArrayName = inputValues.DestinationAttributeMatrix.createChildPath(filterArgs.value(k_HistogramArrayName_Key)); inputValues.MostPopulatedBinArrayName = inputValues.DestinationAttributeMatrix.createChildPath(filterArgs.value(k_MostPopulatedBinArrayName_Key)); + inputValues.ModalBinArrayName = inputValues.DestinationAttributeMatrix.createChildPath(filterArgs.value(k_ModalBinArrayName_Key)); inputValues.LengthArrayName = inputValues.DestinationAttributeMatrix.createChildPath(filterArgs.value(k_LengthArrayName_Key)); inputValues.MinimumArrayName = inputValues.DestinationAttributeMatrix.createChildPath(filterArgs.value(k_MinimumArrayName_Key)); inputValues.MaximumArrayName = inputValues.DestinationAttributeMatrix.createChildPath(filterArgs.value(k_MaximumArrayName_Key)); diff --git a/src/Plugins/ComplexCore/src/ComplexCore/Filters/FindArrayStatisticsFilter.hpp b/src/Plugins/ComplexCore/src/ComplexCore/Filters/FindArrayStatisticsFilter.hpp index 0116e3cbd2..3c634e7535 100644 --- a/src/Plugins/ComplexCore/src/ComplexCore/Filters/FindArrayStatisticsFilter.hpp +++ b/src/Plugins/ComplexCore/src/ComplexCore/Filters/FindArrayStatisticsFilter.hpp @@ -36,6 +36,7 @@ class COMPLEXCORE_EXPORT FindArrayStatisticsFilter : public IFilter static inline constexpr StringLiteral k_FindMean_Key = "find_mean"; static inline constexpr StringLiteral k_FindMedian_Key = "find_median"; static inline constexpr StringLiteral k_FindMode_Key = "find_mode"; + static inline constexpr StringLiteral k_FindModalBinRanges_Key = "find_modal_bin_ranges"; static inline constexpr StringLiteral k_FindStdDeviation_Key = "find_std_deviation"; static inline constexpr StringLiteral k_FindSummation_Key = "find_summation"; static inline constexpr StringLiteral k_FindUniqueValues_Key = "find_unique_values"; @@ -49,6 +50,7 @@ class COMPLEXCORE_EXPORT FindArrayStatisticsFilter : public IFilter static inline constexpr StringLiteral k_DestinationAttributeMatrix_Key = "destination_attribute_matrix"; static inline constexpr StringLiteral k_HistogramArrayName_Key = "histogram_array_name"; static inline constexpr StringLiteral k_MostPopulatedBinArrayName_Key = "most_populated_bin_array_name"; + static inline constexpr StringLiteral k_ModalBinArrayName_Key = "modal_bin_array_name"; static inline constexpr StringLiteral k_LengthArrayName_Key = "length_array_name"; static inline constexpr StringLiteral k_MinimumArrayName_Key = "minimum_array_name"; static inline constexpr StringLiteral k_MaximumArrayName_Key = "maximum_array_name"; diff --git a/src/Plugins/ComplexCore/test/FindArrayStatisticsTest.cpp b/src/Plugins/ComplexCore/test/FindArrayStatisticsTest.cpp index c04d4f64db..702ce9919e 100644 --- a/src/Plugins/ComplexCore/test/FindArrayStatisticsTest.cpp +++ b/src/Plugins/ComplexCore/test/FindArrayStatisticsTest.cpp @@ -54,6 +54,7 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm", "[ComplexCor const std::string histogram = "Histogram"; const std::string mostPopulatedBin = "Most Populated Bin"; + const std::string modalBinRanges = "Modal Bin Ranges"; const std::string length = "Length"; const std::string min = "Minimum"; const std::string max = "Maximum"; @@ -80,6 +81,7 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm", "[ComplexCor args.insertOrAssign(FindArrayStatisticsFilter::k_FindMean_Key, std::make_any(true)); args.insertOrAssign(FindArrayStatisticsFilter::k_FindMedian_Key, std::make_any(true)); args.insertOrAssign(FindArrayStatisticsFilter::k_FindMode_Key, std::make_any(true)); + args.insertOrAssign(FindArrayStatisticsFilter::k_FindModalBinRanges_Key, std::make_any(true)); args.insertOrAssign(FindArrayStatisticsFilter::k_FindStdDeviation_Key, std::make_any(true)); args.insertOrAssign(FindArrayStatisticsFilter::k_FindSummation_Key, std::make_any(true)); args.insertOrAssign(FindArrayStatisticsFilter::k_FindUniqueValues_Key, std::make_any(true)); @@ -92,6 +94,7 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm", "[ComplexCor args.insertOrAssign(FindArrayStatisticsFilter::k_DestinationAttributeMatrix_Key, std::make_any(statsDataPath)); args.insertOrAssign(FindArrayStatisticsFilter::k_HistogramArrayName_Key, std::make_any(histogram)); args.insertOrAssign(FindArrayStatisticsFilter::k_MostPopulatedBinArrayName_Key, std::make_any(mostPopulatedBin)); + args.insertOrAssign(FindArrayStatisticsFilter::k_ModalBinArrayName_Key, std::make_any(modalBinRanges)); args.insertOrAssign(FindArrayStatisticsFilter::k_LengthArrayName_Key, std::make_any(length)); args.insertOrAssign(FindArrayStatisticsFilter::k_MinimumArrayName_Key, std::make_any(min)); args.insertOrAssign(FindArrayStatisticsFilter::k_MaximumArrayName_Key, std::make_any(max)); @@ -141,6 +144,8 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm", "[ComplexCor REQUIRE(histArray != nullptr); auto* mostPopulatedBinArray = dataStructure.getDataAs(statsDataPath.createChildPath(mostPopulatedBin)); REQUIRE(mostPopulatedBinArray != nullptr); + auto* modalBinRangesArray = dataStructure.getDataAs>(statsDataPath.createChildPath(modalBinRanges)); + REQUIRE(modalBinRangesArray != nullptr); auto* numUniqueValuesArray = dataStructure.getDataAs(statsDataPath.createChildPath(numUniqueValues)); REQUIRE(numUniqueValuesArray != nullptr); @@ -150,6 +155,7 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm", "[ComplexCor auto meanVal = (*meanArray)[0]; auto medianVal = (*medianArray)[0]; auto modeVals = (*modeArray).getListReference(0); + auto modalBinRangesVals = (*modalBinRangesArray).getListReference(0); auto stdVal = (*stdArray)[0]; stdVal = std::ceil(stdVal * 100.0f) / 100.0f; // round value to 2 decimal places auto sumVal = (*sumArray)[0]; @@ -160,6 +166,9 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm", "[ComplexCor REQUIRE(maxVal == 45); REQUIRE(modeVals.size() == 1); REQUIRE(modeVals[0] == 1); + REQUIRE(modalBinRangesVals.size() == 2); + REQUIRE(std::fabs(modalBinRangesVals[0] - 1.0f) < UnitTest::EPSILON); + REQUIRE(std::fabs(modalBinRangesVals[1] - 9.8f) < UnitTest::EPSILON); REQUIRE(std::fabs(meanVal - 14.3333f) < UnitTest::EPSILON); REQUIRE(std::fabs(medianVal - 10.0f) < UnitTest::EPSILON); REQUIRE(std::fabs(stdVal - 13.02f) < UnitTest::EPSILON); @@ -248,6 +257,7 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm By Index", "[C const std::string histogram = "Histogram"; const std::string mostPopulatedBin = "Most Populated Bin"; + const std::string modalBinRanges = "Modal Bin Ranges"; const std::string length = "Length"; const std::string min = "Minimum"; const std::string max = "Maximum"; @@ -274,6 +284,7 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm By Index", "[C args.insertOrAssign(FindArrayStatisticsFilter::k_FindMean_Key, std::make_any(true)); args.insertOrAssign(FindArrayStatisticsFilter::k_FindMedian_Key, std::make_any(true)); args.insertOrAssign(FindArrayStatisticsFilter::k_FindMode_Key, std::make_any(true)); + args.insertOrAssign(FindArrayStatisticsFilter::k_FindModalBinRanges_Key, std::make_any(true)); args.insertOrAssign(FindArrayStatisticsFilter::k_FindStdDeviation_Key, std::make_any(true)); args.insertOrAssign(FindArrayStatisticsFilter::k_FindSummation_Key, std::make_any(true)); args.insertOrAssign(FindArrayStatisticsFilter::k_FindUniqueValues_Key, std::make_any(true)); @@ -286,6 +297,7 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm By Index", "[C args.insertOrAssign(FindArrayStatisticsFilter::k_DestinationAttributeMatrix_Key, std::make_any(statsDataPath)); args.insertOrAssign(FindArrayStatisticsFilter::k_HistogramArrayName_Key, std::make_any(histogram)); args.insertOrAssign(FindArrayStatisticsFilter::k_MostPopulatedBinArrayName_Key, std::make_any(mostPopulatedBin)); + args.insertOrAssign(FindArrayStatisticsFilter::k_ModalBinArrayName_Key, std::make_any(modalBinRanges)); args.insertOrAssign(FindArrayStatisticsFilter::k_LengthArrayName_Key, std::make_any(length)); args.insertOrAssign(FindArrayStatisticsFilter::k_MinimumArrayName_Key, std::make_any(min)); args.insertOrAssign(FindArrayStatisticsFilter::k_MaximumArrayName_Key, std::make_any(max)); @@ -346,6 +358,9 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm By Index", "[C auto* mostPopulatedBinArray = dataStructure.getDataAs(statsDataPath.createChildPath(mostPopulatedBin)); REQUIRE(mostPopulatedBinArray != nullptr); REQUIRE(mostPopulatedBinArray->getNumberOfTuples() == 3); + auto* modalBinRangesArray = dataStructure.getDataAs>(statsDataPath.createChildPath(modalBinRanges)); + REQUIRE(modalBinRangesArray != nullptr); + REQUIRE(modalBinRangesArray->getNumberOfTuples() == 3); auto* numUniqueValuesArray = dataStructure.getDataAs(statsDataPath.createChildPath(numUniqueValues)); REQUIRE(numUniqueValuesArray != nullptr); REQUIRE(numUniqueValuesArray->getNumberOfTuples() == 3); @@ -368,6 +383,9 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm By Index", "[C auto modes0 = (*modeArray).getListReference(0); auto modes1 = (*modeArray).getListReference(1); auto modes2 = (*modeArray).getListReference(2); + auto modalBinRange0 = (*modalBinRangesArray).getListReference(0); + auto modalBinRange1 = (*modalBinRangesArray).getListReference(1); + auto modalBinRange2 = (*modalBinRangesArray).getListReference(2); auto stdVal1 = (*stdArray)[0]; auto stdVal2 = (*stdArray)[1]; auto stdVal3 = (*stdArray)[2]; @@ -469,5 +487,15 @@ TEST_CASE("ComplexCore::FindArrayStatisticsFilter: Test Algorithm By Index", "[C REQUIRE((*mostPopulatedBinArray)[3] == 2); REQUIRE((*mostPopulatedBinArray)[4] == 0); REQUIRE((*mostPopulatedBinArray)[5] == 2); + REQUIRE(std::fabs(modalBinRange0[0] - 1.0f) < UnitTest::EPSILON); + REQUIRE(std::fabs(modalBinRange0[1] - 15.4f) < UnitTest::EPSILON); + REQUIRE(std::fabs(modalBinRange0[2] - 58.6f) < UnitTest::EPSILON); + REQUIRE(std::fabs(modalBinRange0[3] - 73.0f) < UnitTest::EPSILON); + REQUIRE(std::fabs(modalBinRange1[0] - 17.0f) < UnitTest::EPSILON); + REQUIRE(std::fabs(modalBinRange1[1] - 20.0f) < UnitTest::EPSILON); + REQUIRE(std::fabs(modalBinRange2[0] - 10.0f) < UnitTest::EPSILON); + REQUIRE(std::fabs(modalBinRange2[1] - 12.4f) < UnitTest::EPSILON); + REQUIRE(std::fabs(modalBinRange2[2] - 19.6f) < UnitTest::EPSILON); + REQUIRE(std::fabs(modalBinRange2[3] - 22.0f) < UnitTest::EPSILON); } } diff --git a/src/complex/Utilities/Math/StatisticsCalculations.hpp b/src/complex/Utilities/Math/StatisticsCalculations.hpp index 364e4516a8..29a306fdab 100644 --- a/src/complex/Utilities/Math/StatisticsCalculations.hpp +++ b/src/complex/Utilities/Math/StatisticsCalculations.hpp @@ -236,13 +236,8 @@ size_t findNumUniqueValues(const C& source) // ----------------------------------------------------------------------------- template