diff --git a/CMakeLists.txt b/CMakeLists.txt
index d887159..2c65f55 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,6 +27,7 @@ set(${PLUGIN_NAME}_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR})
# These are all the filters in the plugin. All filters should be kept in the
# SimplnxReview/src/SimplnxReview/Filters/ directory.
set(FilterList
+ ComputeArrayNormFilter
ComputeGroupingDensityFilter
ComputeLocalAverageCAxisMisalignmentsFilter
ComputeMicroTextureRegionsFilter
@@ -44,6 +45,7 @@ set(ActionList
# This should be integrated with the `create_simplnx_plugin` function call
# ------------------------------------------------------------------------------
set(AlgorithmList
+ ComputeArrayNorm
ComputeGroupingDensity
ComputeLocalAverageCAxisMisalignments
ComputeMicroTextureRegions
diff --git a/docs/ComputeArrayNormFilter.md b/docs/ComputeArrayNormFilter.md
new file mode 100644
index 0000000..86d5d13
--- /dev/null
+++ b/docs/ComputeArrayNormFilter.md
@@ -0,0 +1,32 @@
+# Compute Array Norm
+
+## Group (Subgroup)
+
+SimplnxReview (Statistics)
+
+## Description
+
+This **Filter** computes the pth norm of an **Attribute Array**. Specifically, for each tuple of the array, the following is computed:
+
+$$\left\| \mathbf{x} \right\| _p := \bigg( \sum_{i=1}^n \left| x_i \right| ^p \bigg) ^{1/p}$$
+
+where $n$ is the number of components for the **Attribute Array**.
+
+- When $p = 2$, this results in the *Euclidean norm*
+- When $p = 1$, this results in the *Manhattan norm* (also called the *taxicab norm*)
+
+The p-space value may be any real number greater than or equal to zero. When $0 \leq p < 1$, the result may not strictly be a *norm* in the exact mathematical sense. Additionally, when $p = 0$, the result is simply the number of components for the **Attribute Array**.
+
+**Note:** If the input array is a scalar array (1 component), the output array will contain the same values as the input array, but in 32-bit floating point precision.
+
+% Auto generated parameter table will be inserted here
+
+## Example Pipelines
+
+## License & Copyright
+
+Please see the description file distributed with this plugin.
+
+## DREAM3D-NX Help
+
+If you need help, need to file a bug report or want to request a new feature, please head over to the [DREAM3DNX-Issues](https://github.com/BlueQuartzSoftware/DREAM3DNX-Issues/discussions) GitHub site where the community of DREAM3D-NX users can help answer your questions.
diff --git a/src/SimplnxReview/Filters/Algorithms/ComputeArrayNorm.cpp b/src/SimplnxReview/Filters/Algorithms/ComputeArrayNorm.cpp
new file mode 100644
index 0000000..ffc4a20
--- /dev/null
+++ b/src/SimplnxReview/Filters/Algorithms/ComputeArrayNorm.cpp
@@ -0,0 +1,87 @@
+#include "ComputeArrayNorm.hpp"
+
+#include "simplnx/DataStructure/DataArray.hpp"
+#include "simplnx/Utilities/DataArrayUtilities.hpp"
+#include "simplnx/Utilities/FilterUtilities.hpp"
+
+#include
+
+using namespace nx::core;
+
+namespace
+{
+template
+class ComputeNormImpl
+{
+public:
+ ComputeNormImpl(const IDataArray& inputArray, Float32Array& normArray, float32 pSpace)
+ : m_InputArray(dynamic_cast&>(inputArray))
+ , m_NormArray(normArray)
+ , m_PSpace(pSpace)
+ {
+ }
+
+ void operator()() const
+ {
+ const auto& inputStore = m_InputArray.getDataStoreRef();
+ auto& normStore = m_NormArray.getDataStoreRef();
+
+ usize numTuples = m_InputArray.getNumberOfTuples();
+ usize numComponents = m_InputArray.getNumberOfComponents();
+
+ for(usize i = 0; i < numTuples; i++)
+ {
+ float32 normTmp = 0.0f;
+ for(usize j = 0; j < numComponents; j++)
+ {
+ float32 value = static_cast(inputStore[numComponents * i + j]);
+ normTmp += std::pow(std::abs(value), m_PSpace);
+ }
+ normStore[i] = std::pow(normTmp, 1.0f / m_PSpace);
+ }
+ }
+
+private:
+ const DataArray& m_InputArray;
+ Float32Array& m_NormArray;
+ float32 m_PSpace;
+};
+
+struct ComputeNormFunctor
+{
+ template
+ void operator()(const IDataArray& inputArray, Float32Array& normArray, float32 pSpace)
+ {
+ ComputeNormImpl(inputArray, normArray, pSpace)();
+ }
+};
+} // namespace
+
+// -----------------------------------------------------------------------------
+ComputeArrayNorm::ComputeArrayNorm(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeArrayNormInputValues* inputValues)
+: m_DataStructure(dataStructure)
+, m_InputValues(inputValues)
+, m_ShouldCancel(shouldCancel)
+, m_MessageHandler(mesgHandler)
+{
+}
+
+// -----------------------------------------------------------------------------
+ComputeArrayNorm::~ComputeArrayNorm() noexcept = default;
+
+// -----------------------------------------------------------------------------
+const std::atomic_bool& ComputeArrayNorm::getCancel()
+{
+ return m_ShouldCancel;
+}
+
+// -----------------------------------------------------------------------------
+Result<> ComputeArrayNorm::operator()()
+{
+ const auto& inputArray = m_DataStructure.getDataRefAs(m_InputValues->SelectedArrayPath);
+ auto& normArray = m_DataStructure.getDataRefAs(m_InputValues->NormArrayPath);
+
+ ExecuteDataFunction(ComputeNormFunctor{}, inputArray.getDataType(), inputArray, normArray, m_InputValues->PSpace);
+
+ return {};
+}
diff --git a/src/SimplnxReview/Filters/Algorithms/ComputeArrayNorm.hpp b/src/SimplnxReview/Filters/Algorithms/ComputeArrayNorm.hpp
new file mode 100644
index 0000000..44af109
--- /dev/null
+++ b/src/SimplnxReview/Filters/Algorithms/ComputeArrayNorm.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "SimplnxReview/SimplnxReview_export.hpp"
+
+#include "simplnx/DataStructure/DataPath.hpp"
+#include "simplnx/DataStructure/DataStructure.hpp"
+#include "simplnx/Filter/IFilter.hpp"
+
+namespace nx::core
+{
+
+struct SIMPLNXREVIEW_EXPORT ComputeArrayNormInputValues
+{
+ float32 PSpace;
+ DataPath SelectedArrayPath;
+ DataPath NormArrayPath;
+};
+
+/**
+ * @class ComputeArrayNorm
+ * @brief This algorithm computes the p-th norm of an Attribute Array.
+ */
+class SIMPLNXREVIEW_EXPORT ComputeArrayNorm
+{
+public:
+ ComputeArrayNorm(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeArrayNormInputValues* inputValues);
+ ~ComputeArrayNorm() noexcept;
+
+ ComputeArrayNorm(const ComputeArrayNorm&) = delete;
+ ComputeArrayNorm(ComputeArrayNorm&&) noexcept = delete;
+ ComputeArrayNorm& operator=(const ComputeArrayNorm&) = delete;
+ ComputeArrayNorm& operator=(ComputeArrayNorm&&) noexcept = delete;
+
+ Result<> operator()();
+
+ const std::atomic_bool& getCancel();
+
+private:
+ DataStructure& m_DataStructure;
+ const ComputeArrayNormInputValues* m_InputValues = nullptr;
+ const std::atomic_bool& m_ShouldCancel;
+ const IFilter::MessageHandler& m_MessageHandler;
+};
+
+} // namespace nx::core
diff --git a/src/SimplnxReview/Filters/Algorithms/ComputeGroupingDensity.cpp b/src/SimplnxReview/Filters/Algorithms/ComputeGroupingDensity.cpp
deleted file mode 100644
index 31e20a2..0000000
--- a/src/SimplnxReview/Filters/Algorithms/ComputeGroupingDensity.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-#include "ComputeGroupingDensity.hpp"
-
-#include "simplnx/DataStructure/DataArray.hpp"
-#include "simplnx/DataStructure/NeighborList.hpp"
-#include "simplnx/Utilities/MessageHelper.hpp"
-
-using namespace nx::core;
-
-namespace
-{
-template
-struct FindDensitySpecializations
-{
- static inline constexpr bool UsingNonContiguousNeighbors = UseNonContiguousNeighbors;
- static inline constexpr bool FindingCheckedFeatures = FindCheckedFeatures;
-};
-
-template >
-class FindDensityGrouping
-{
-public:
- FindDensityGrouping(const std::atomic_bool& shouldCancel, const IFilter::MessageHandler& mesgHandler, const Int32Array& parentIds, const Float32Array& parentVolumes, const Float32Array& volumes,
- const Int32NeighborList& contiguousNL, Float32Array& groupingDensities, Int32NeighborList& nonContiguousNL, Int32Array& checkedFeatures)
- : m_ShouldCancel(shouldCancel)
- , m_MessageHandler(mesgHandler)
- , m_ParentIds(parentIds)
- , m_ParentVolumes(parentVolumes)
- , m_Volumes(volumes)
- , m_ContiguousNL(contiguousNL)
- , m_GroupingDensities(groupingDensities)
- , m_NonContiguousNL(nonContiguousNL)
- , m_CheckedFeatures(checkedFeatures)
- {
- }
- ~FindDensityGrouping() noexcept = default;
-
- FindDensityGrouping(const FindDensityGrouping&) = delete; // Copy Constructor Default Implemented
- FindDensityGrouping(FindDensityGrouping&&) = delete; // Move Constructor Not Implemented
- FindDensityGrouping& operator=(const FindDensityGrouping&) = delete; // Copy Assignment Not Implemented
- FindDensityGrouping& operator=(FindDensityGrouping&&) = delete; // Move Assignment Not Implemented
-
- Result<> operator()()
- {
- const auto& parentIds = m_ParentIds.getDataStoreRef();
- const auto& parentVolumes = m_ParentVolumes.getDataStoreRef();
- const auto& volumes = m_Volumes.getDataStoreRef();
-
- auto& checkedFeatures = m_CheckedFeatures.getDataStoreRef();
- auto& groupingDensities = m_GroupingDensities.getDataStoreRef();
-
- usize numFeatures = volumes.getNumberOfTuples();
- usize numParents = parentVolumes.getNumberOfTuples();
-
- int kMax = 1;
- if constexpr(FindDensitySpecializations::UsingNonContiguousNeighbors)
- {
- kMax = 2;
- }
-
- int32 numNeighbors, numNeighborhoods, numCurNeighborList, neigh;
- float32 totalCheckVolume, curParentVolume;
- std::set totalCheckList = {};
-
- std::vector checkedFeatureVolumes(1, 0.0f);
- if constexpr(FindDensitySpecializations::FindingCheckedFeatures)
- {
- // Default value-initialized to zeroes: https://en.cppreference.com/w/cpp/named_req/DefaultInsertable
- checkedFeatureVolumes.resize(numFeatures);
- }
- MessageHelper messageHelper(m_MessageHandler);
- ThrottledMessenger throttledMessenger = messageHelper.createThrottledMessenger();
-
- for(usize parentIdx = 1; parentIdx < numParents; parentIdx++)
- {
- throttledMessenger.sendThrottledMessage([&]() { return fmt::format("[{}%]", CalculatePercentComplete(parentIdx, numParents)); });
-
- if(m_ShouldCancel)
- {
- return {};
- }
- for(usize j = 1; j < numFeatures; j++)
- {
- if(parentIds[j] == parentIdx)
- {
- if(totalCheckList.find(j) == totalCheckList.end())
- // if(std::find(totalCheckList.begin(), totalCheckList.end(), j) == totalCheckList.end())
- {
- totalCheckVolume += m_Volumes[j];
- totalCheckList.insert(static_cast(j));
- if constexpr(FindDensitySpecializations::FindingCheckedFeatures)
- {
- if(parentVolumes[parentIdx] > checkedFeatureVolumes[j])
- {
- checkedFeatureVolumes[j] = parentVolumes[parentIdx];
- checkedFeatures[j] = static_cast(parentIdx);
- }
- }
- }
- numNeighbors = m_ContiguousNL.getListSize(static_cast(j));
- if constexpr(FindDensitySpecializations::UsingNonContiguousNeighbors)
- {
- numNeighborhoods = static_cast(m_NonContiguousNL[j].size());
- }
- for(int k = 0; k < kMax; k++)
- {
- if(k == 0)
- {
- numCurNeighborList = numNeighbors;
- }
- if constexpr(FindDensitySpecializations::UsingNonContiguousNeighbors)
- {
- if(k == 1)
- {
- numCurNeighborList = numNeighborhoods;
- }
- }
- for(int32_t l = 0; l < numCurNeighborList; l++)
- {
- if(k == 0)
- {
- bool ok = false;
- neigh = m_ContiguousNL.getValue(static_cast(j), l, ok);
- }
- else if(k == 1)
- {
- neigh = m_NonContiguousNL[j][l];
- }
- if(totalCheckList.find(neigh) == totalCheckList.end())
- // if(std::find(totalCheckList.begin(), totalCheckList.end(), neigh) == totalCheckList.end())
- {
- totalCheckVolume += m_Volumes[neigh];
- totalCheckList.insert(neigh);
- if constexpr(FindDensitySpecializations::FindingCheckedFeatures)
- {
- if(parentVolumes[parentIdx] > checkedFeatureVolumes[neigh])
- {
- checkedFeatureVolumes[neigh] = parentVolumes[parentIdx];
- checkedFeatures[neigh] = static_cast(parentIdx);
- }
- }
- }
- }
- }
- }
- }
- curParentVolume = parentVolumes[parentIdx];
- if(totalCheckVolume == 0.0f)
- {
- groupingDensities[parentIdx] = -1.0f;
- }
- else
- {
- groupingDensities[parentIdx] = (curParentVolume / totalCheckVolume);
- }
- totalCheckList.clear();
- totalCheckVolume = 0.0f;
- }
-
- return {};
- }
-
-private:
- const std::atomic_bool& m_ShouldCancel;
- const IFilter::MessageHandler& m_MessageHandler;
- const Int32Array& m_ParentIds;
- const Float32Array& m_ParentVolumes;
- const Float32Array& m_Volumes;
- const Int32NeighborList& m_ContiguousNL;
- Float32Array& m_GroupingDensities;
- Int32NeighborList& m_NonContiguousNL;
- Int32Array& m_CheckedFeatures;
-};
-} // namespace
-
-// -----------------------------------------------------------------------------
-ComputeGroupingDensity::ComputeGroupingDensity(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel,
- ComputeGroupingDensityInputValues* inputValues)
-: m_DataStructure(dataStructure)
-, m_InputValues(inputValues)
-, m_ShouldCancel(shouldCancel)
-, m_MessageHandler(mesgHandler)
-{
-}
-
-// -----------------------------------------------------------------------------
-const std::atomic_bool& ComputeGroupingDensity::getCancel()
-{
- return m_ShouldCancel;
-}
-
-// -----------------------------------------------------------------------------
-Result<> ComputeGroupingDensity::operator()()
-{
- auto& parentIds = m_DataStructure.getDataRefAs(m_InputValues->ParentIdsPath);
- auto& parentVolumes = m_DataStructure.getDataRefAs(m_InputValues->ParentVolumesPath);
- auto& volumes = m_DataStructure.getDataRefAs(m_InputValues->VolumesPath);
- auto& contiguousNL = m_DataStructure.getDataRefAs>(m_InputValues->ContiguousNLPath);
- auto& groupingDensities = m_DataStructure.getDataRefAs(m_InputValues->GroupingDensitiesPath);
-
- // These may or may not be empty depending on the parameters
- auto& nonContiguousNL = m_DataStructure.getDataRefAs>(m_InputValues->NonContiguousNLPath);
- auto& checkedFeatures = m_DataStructure.getDataRefAs(m_InputValues->CheckedFeaturesPath);
-
- if(m_InputValues->UseNonContiguousNeighbors)
- {
- if(m_InputValues->FindCheckedFeatures)
- {
- return ::FindDensityGrouping>(getCancel(), m_MessageHandler, parentIds, parentVolumes, volumes, contiguousNL, groupingDensities, nonContiguousNL,
- checkedFeatures)();
- }
- return ::FindDensityGrouping>(getCancel(), m_MessageHandler, parentIds, parentVolumes, volumes, contiguousNL, groupingDensities, nonContiguousNL,
- checkedFeatures)();
- }
- else if(m_InputValues->FindCheckedFeatures)
- {
- return ::FindDensityGrouping>(getCancel(), m_MessageHandler, parentIds, parentVolumes, volumes, contiguousNL, groupingDensities, nonContiguousNL,
- checkedFeatures)();
- }
- else
- {
- return ::FindDensityGrouping>(getCancel(), m_MessageHandler, parentIds, parentVolumes, volumes, contiguousNL, groupingDensities, nonContiguousNL,
- checkedFeatures)();
- }
-}
diff --git a/src/SimplnxReview/Filters/Algorithms/ComputeGroupingDensity.hpp b/src/SimplnxReview/Filters/Algorithms/ComputeGroupingDensity.hpp
deleted file mode 100644
index 3b2dc60..0000000
--- a/src/SimplnxReview/Filters/Algorithms/ComputeGroupingDensity.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include "SimplnxReview/SimplnxReview_export.hpp"
-
-#include "simplnx/DataStructure/DataPath.hpp"
-#include "simplnx/DataStructure/DataStructure.hpp"
-#include "simplnx/Filter/IFilter.hpp"
-
-namespace nx::core
-{
-
-struct SIMPLNXREVIEW_EXPORT ComputeGroupingDensityInputValues
-{
- DataPath VolumesPath;
- DataPath ContiguousNLPath;
- bool UseNonContiguousNeighbors;
- DataPath NonContiguousNLPath;
- DataPath ParentIdsPath;
- DataPath ParentVolumesPath;
- bool FindCheckedFeatures;
- DataPath CheckedFeaturesPath;
- DataPath GroupingDensitiesPath;
-};
-
-/**
- * @class ComputeGroupingDensity
- * @brief This filter determines the average C-axis location of each Feature.
- */
-
-class SIMPLNXREVIEW_EXPORT ComputeGroupingDensity
-{
-public:
- ComputeGroupingDensity(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeGroupingDensityInputValues* inputValues);
- ~ComputeGroupingDensity() noexcept = default;
-
- ComputeGroupingDensity(const ComputeGroupingDensity&) = delete;
- ComputeGroupingDensity(ComputeGroupingDensity&&) noexcept = delete;
- ComputeGroupingDensity& operator=(const ComputeGroupingDensity&) = delete;
- ComputeGroupingDensity& operator=(ComputeGroupingDensity&&) noexcept = delete;
-
- Result<> operator()();
-
- const std::atomic_bool& getCancel();
-
-private:
- DataStructure& m_DataStructure;
- const ComputeGroupingDensityInputValues* m_InputValues = nullptr;
- const std::atomic_bool& m_ShouldCancel;
- const IFilter::MessageHandler& m_MessageHandler;
-};
-
-} // namespace nx::core
diff --git a/src/SimplnxReview/Filters/ComputeArrayNormFilter.cpp b/src/SimplnxReview/Filters/ComputeArrayNormFilter.cpp
new file mode 100644
index 0000000..79b5157
--- /dev/null
+++ b/src/SimplnxReview/Filters/ComputeArrayNormFilter.cpp
@@ -0,0 +1,149 @@
+#include "ComputeArrayNormFilter.hpp"
+
+#include "SimplnxReview/Filters/Algorithms/ComputeArrayNorm.hpp"
+
+#include "simplnx/DataStructure/DataArray.hpp"
+#include "simplnx/DataStructure/DataPath.hpp"
+#include "simplnx/Filter/Actions/CreateArrayAction.hpp"
+#include "simplnx/Parameters/ArraySelectionParameter.hpp"
+#include "simplnx/Parameters/DataObjectNameParameter.hpp"
+#include "simplnx/Parameters/NumberParameter.hpp"
+#include "simplnx/Utilities/SIMPLConversion.hpp"
+
+using namespace nx::core;
+
+namespace nx::core
+{
+//------------------------------------------------------------------------------
+std::string ComputeArrayNormFilter::name() const
+{
+ return FilterTraits::name.str();
+}
+
+//------------------------------------------------------------------------------
+std::string ComputeArrayNormFilter::className() const
+{
+ return FilterTraits::className;
+}
+
+//------------------------------------------------------------------------------
+Uuid ComputeArrayNormFilter::uuid() const
+{
+ return FilterTraits::uuid;
+}
+
+//------------------------------------------------------------------------------
+std::string ComputeArrayNormFilter::humanName() const
+{
+ return "Compute Array Norm";
+}
+
+//------------------------------------------------------------------------------
+std::vector ComputeArrayNormFilter::defaultTags() const
+{
+ return {className(), "Statistics", "DREAM3DReview"};
+}
+
+//------------------------------------------------------------------------------
+Parameters ComputeArrayNormFilter::parameters() const
+{
+ Parameters params;
+
+ params.insertSeparator(Parameters::Separator{"Input Parameter"});
+ params.insert(std::make_unique(k_PSpace_Key, "p-Space Value", "p-Value used for computing the norm (2 = Euclidean, 1 = Manhattan)", 2.0f));
+
+ params.insertSeparator(Parameters::Separator{"Input Data"});
+ params.insert(std::make_unique(k_SelectedArrayPath_Key, "Input Attribute Array", "The input array for computing the norm", DataPath{},
+ ArraySelectionParameter::AllowedTypes{DataType::int8, DataType::uint8, DataType::int16, DataType::uint16, DataType::int32, DataType::uint32,
+ DataType::int64, DataType::uint64, DataType::float32, DataType::float64},
+ ArraySelectionParameter::AllowedComponentShapes{}));
+
+ params.insertSeparator(Parameters::Separator{"Output Data"});
+ params.insert(std::make_unique(k_NormArrayName_Key, "Norm Array Name", "The name of the output norm array", "Norm"));
+
+ return params;
+}
+
+//------------------------------------------------------------------------------
+IFilter::UniquePointer ComputeArrayNormFilter::clone() const
+{
+ return std::make_unique();
+}
+
+//------------------------------------------------------------------------------
+IFilter::VersionType ComputeArrayNormFilter::parametersVersion() const
+{
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+IFilter::PreflightResult ComputeArrayNormFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler,
+ const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const
+{
+ auto pSpaceValue = filterArgs.value(k_PSpace_Key);
+ auto pSelectedArrayPathValue = filterArgs.value(k_SelectedArrayPath_Key);
+ auto pNormArrayNameValue = filterArgs.value(k_NormArrayName_Key);
+
+ PreflightResult preflightResult;
+ nx::core::Result resultOutputActions;
+ std::vector preflightUpdatedValues;
+
+ if(pSpaceValue < 0.0f)
+ {
+ return {MakeErrorResult(-11002, "p-space value must be greater than or equal to 0")};
+ }
+
+ const auto* inputArray = dataStructure.getDataAs(pSelectedArrayPathValue);
+ if(inputArray == nullptr)
+ {
+ return {MakeErrorResult(-11003, fmt::format("Cannot find the selected input array at path '{}'", pSelectedArrayPathValue.toString()))};
+ }
+
+ DataPath normArrayPath = pSelectedArrayPathValue.replaceName(pNormArrayNameValue);
+
+ {
+ auto createArrayAction = std::make_unique(DataType::float32, inputArray->getTupleShape(), std::vector{1}, normArrayPath);
+ resultOutputActions.value().appendAction(std::move(createArrayAction));
+ }
+
+ return {std::move(resultOutputActions), std::move(preflightUpdatedValues)};
+}
+
+//------------------------------------------------------------------------------
+Result<> ComputeArrayNormFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler,
+ const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const
+{
+ ComputeArrayNormInputValues inputValues;
+
+ inputValues.PSpace = filterArgs.value(k_PSpace_Key);
+ inputValues.SelectedArrayPath = filterArgs.value(k_SelectedArrayPath_Key);
+ inputValues.NormArrayPath = inputValues.SelectedArrayPath.replaceName(filterArgs.value(k_NormArrayName_Key));
+
+ return ComputeArrayNorm(dataStructure, messageHandler, shouldCancel, &inputValues)();
+}
+
+namespace
+{
+namespace SIMPL
+{
+constexpr StringLiteral k_SelectedArrayPathKey = "SelectedArrayPath";
+constexpr StringLiteral k_NormArrayPathKey = "NormArrayPath";
+constexpr StringLiteral k_PSpaceKey = "PSpace";
+} // namespace SIMPL
+} // namespace
+
+Result ComputeArrayNormFilter::FromSIMPLJson(const nlohmann::json& json)
+{
+ Arguments args = ComputeArrayNormFilter().getDefaultArguments();
+
+ std::vector> results;
+
+ results.push_back(SIMPLConversion::ConvertParameter>(args, json, SIMPL::k_PSpaceKey, k_PSpace_Key));
+ results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_SelectedArrayPathKey, k_SelectedArrayPath_Key));
+ results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_NormArrayPathKey, k_NormArrayName_Key));
+
+ Result<> conversionResult = MergeResults(std::move(results));
+
+ return ConvertResultTo(std::move(conversionResult), std::move(args));
+}
+} // namespace nx::core
diff --git a/src/SimplnxReview/Filters/ComputeGroupingDensityFilter.hpp b/src/SimplnxReview/Filters/ComputeArrayNormFilter.hpp
similarity index 70%
rename from src/SimplnxReview/Filters/ComputeGroupingDensityFilter.hpp
rename to src/SimplnxReview/Filters/ComputeArrayNormFilter.hpp
index 0614178..757fd66 100644
--- a/src/SimplnxReview/Filters/ComputeGroupingDensityFilter.hpp
+++ b/src/SimplnxReview/Filters/ComputeArrayNormFilter.hpp
@@ -8,31 +8,27 @@
namespace nx::core
{
/**
- * @class ComputeGroupingDensityFilter
- * @brief This filter determines the average C-axis location of each Feature
+ * @class ComputeArrayNormFilter
+ * @brief This filter computes the p-th norm of an Attribute Array. For each tuple of the array,
+ * the norm is calculated as: ||x||_p = (sum(|x_i|^p))^(1/p) where n is the number of components.
+ * When p=2, this results in the Euclidean norm; when p=1, this results in the Manhattan norm.
*/
-class SIMPLNXREVIEW_EXPORT ComputeGroupingDensityFilter : public IFilter
+class SIMPLNXREVIEW_EXPORT ComputeArrayNormFilter : public IFilter
{
public:
- ComputeGroupingDensityFilter() = default;
- ~ComputeGroupingDensityFilter() noexcept override = default;
+ ComputeArrayNormFilter() = default;
+ ~ComputeArrayNormFilter() noexcept override = default;
- ComputeGroupingDensityFilter(const ComputeGroupingDensityFilter&) = delete;
- ComputeGroupingDensityFilter(ComputeGroupingDensityFilter&&) noexcept = delete;
+ ComputeArrayNormFilter(const ComputeArrayNormFilter&) = delete;
+ ComputeArrayNormFilter(ComputeArrayNormFilter&&) noexcept = delete;
- ComputeGroupingDensityFilter& operator=(const ComputeGroupingDensityFilter&) = delete;
- ComputeGroupingDensityFilter& operator=(ComputeGroupingDensityFilter&&) noexcept = delete;
+ ComputeArrayNormFilter& operator=(const ComputeArrayNormFilter&) = delete;
+ ComputeArrayNormFilter& operator=(ComputeArrayNormFilter&&) noexcept = delete;
// Parameter Keys
- static constexpr StringLiteral k_VolumesArrayPath_Key = "volumes_path";
- static constexpr StringLiteral k_ContiguousNeighborListArrayPath_Key = "contiguous_neighbor_list_path";
- static constexpr StringLiteral k_UseNonContiguousNeighbors_Key = "use_non_contiguous_neighbors";
- static constexpr StringLiteral k_NonContiguousNeighborListArrayPath_Key = "non_contiguous_neighbor_list_path";
- static constexpr StringLiteral k_ParentIdsPath_Key = "parent_ids_path";
- static constexpr StringLiteral k_ParentVolumesPath_Key = "parent_volumes_path";
- static constexpr StringLiteral k_FindCheckedFeatures_Key = "find_checked_features";
- static constexpr StringLiteral k_CheckedFeaturesName_Key = "checked_features_name";
- static constexpr StringLiteral k_GroupingDensitiesName_Key = "grouping_densities_name";
+ static constexpr StringLiteral k_PSpace_Key = "p_space_value";
+ static constexpr StringLiteral k_SelectedArrayPath_Key = "selected_array_path";
+ static constexpr StringLiteral k_NormArrayName_Key = "norm_array_name";
/**
* @brief Reads SIMPL json and converts it simplnx Arguments.
@@ -122,5 +118,5 @@ class SIMPLNXREVIEW_EXPORT ComputeGroupingDensityFilter : public IFilter
};
} // namespace nx::core
-SIMPLNX_DEF_FILTER_TRAITS(nx::core, ComputeGroupingDensityFilter, "ff46afcf-de32-4f37-98bc-8f0fd4b3c122");
-/* LEGACY UUID FOR THIS FILTER 708be082-8b08-4db2-94be-52781ed4d53d */
+SIMPLNX_DEF_FILTER_TRAITS(nx::core, ComputeArrayNormFilter, "a9943ec6-1276-46d1-b9a4-c1537e8e5d5f");
+/* LEGACY UUID FOR THIS FILTER 5d0cd577-3e3e-57b8-a36d-b215b834251f */
diff --git a/src/SimplnxReview/Filters/ComputeGroupingDensityFilter.cpp b/src/SimplnxReview/Filters/ComputeGroupingDensityFilter.cpp
deleted file mode 100644
index a2f79ff..0000000
--- a/src/SimplnxReview/Filters/ComputeGroupingDensityFilter.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-#include "ComputeGroupingDensityFilter.hpp"
-
-#include "SimplnxReview/Filters/Algorithms/ComputeGroupingDensity.hpp"
-
-#include "simplnx/DataStructure/AttributeMatrix.hpp"
-#include "simplnx/DataStructure/DataPath.hpp"
-#include "simplnx/Filter/Actions/CreateArrayAction.hpp"
-#include "simplnx/Filter/Actions/CreateNeighborListAction.hpp"
-#include "simplnx/Filter/Actions/DeleteDataAction.hpp"
-#include "simplnx/Parameters/ArraySelectionParameter.hpp"
-#include "simplnx/Parameters/BoolParameter.hpp"
-#include "simplnx/Parameters/DataObjectNameParameter.hpp"
-#include "simplnx/Parameters/NeighborListSelectionParameter.hpp"
-#include "simplnx/Utilities/SIMPLConversion.hpp"
-
-using namespace nx::core;
-
-namespace
-{
-const DataPath k_ThrowawayCheckedFeatures = DataPath({"HiddenTempCheckedFeatures"});
-const DataPath k_ThrowawayNonContiguous = DataPath({"HiddenContiguousNL"});
-} // namespace
-
-namespace nx::core
-{
-//------------------------------------------------------------------------------
-std::string ComputeGroupingDensityFilter::name() const
-{
- return FilterTraits::name.str();
-}
-
-//------------------------------------------------------------------------------
-std::string ComputeGroupingDensityFilter::className() const
-{
- return FilterTraits::className;
-}
-
-//------------------------------------------------------------------------------
-Uuid ComputeGroupingDensityFilter::uuid() const
-{
- return FilterTraits::uuid;
-}
-
-//------------------------------------------------------------------------------
-std::string ComputeGroupingDensityFilter::humanName() const
-{
- return "Compute Grouping Densities";
-}
-
-//------------------------------------------------------------------------------
-std::vector ComputeGroupingDensityFilter::defaultTags() const
-{
- return {className(), "Statistics", "Reconstruction"};
-}
-
-//------------------------------------------------------------------------------
-Parameters ComputeGroupingDensityFilter::parameters() const
-{
- Parameters params;
- // Create the parameter descriptors that are needed for this filter
- params.insertSeparator(Parameters::Separator{"Input Parameter(s)"});
- params.insertLinkableParameter(std::make_unique(k_FindCheckedFeatures_Key, "Find Checked Features", "Find checked features", false));
-
- params.insertSeparator(Parameters::Separator{"Non-Contiguous Neighborhood Option"});
- params.insertLinkableParameter(std::make_unique(k_UseNonContiguousNeighbors_Key, "Use Non-Contiguous Neighbors", "Use non-contiguous neighborhoods for computations", false));
- params.insert(std::make_unique(k_NonContiguousNeighborListArrayPath_Key, "Non-Contiguous Neighborhoods", "List of non-contiguous neighbors for each Feature.",
- DataPath{}, NeighborListSelectionParameter::AllowedTypes{DataType::int32}));
-
- params.insertSeparator(Parameters::Separator{"Input Cell Data"});
- params.insert(std::make_unique(k_ParentIdsPath_Key, "Parent Ids", "Input Cell level ParentIds", DataPath{}, ArraySelectionParameter::AllowedTypes{DataType::int32},
- ArraySelectionParameter::AllowedComponentShapes{{1}}));
-
- params.insertSeparator(Parameters::Separator{"Input Feature Data"});
- params.insert(std::make_unique(k_VolumesArrayPath_Key, "Volumes", "The Feature Volumes Data Array", DataPath{},
- ArraySelectionParameter::AllowedTypes{nx::core::DataType::float32}, ArraySelectionParameter::AllowedComponentShapes{{1}}));
-
- params.insert(std::make_unique(k_ContiguousNeighborListArrayPath_Key, "Contiguous Neighbor List", "List of contiguous neighbors for each Feature.", DataPath{},
- NeighborListSelectionParameter::AllowedTypes{DataType::int32}));
-
- params.insert(std::make_unique(k_ParentVolumesPath_Key, "Parent Volumes", "Input feature level parent volume data array", DataPath{},
- ArraySelectionParameter::AllowedTypes{DataType::float32}, ArraySelectionParameter::AllowedComponentShapes{{1}}));
-
- params.insertSeparator(Parameters::Separator{"Output Feature Data"});
-
- params.insert(std::make_unique(k_CheckedFeaturesName_Key, "Checked Features Name", "Output feature level data array to hold 'Checked Features' values", "Checked Features"));
- params.insert(
- std::make_unique(k_GroupingDensitiesName_Key, "Grouping Densities Name", "Output feature level data array to hold 'Grouping Densities' values", "Grouping Densities"));
-
- // Link params
- params.linkParameters(k_UseNonContiguousNeighbors_Key, k_NonContiguousNeighborListArrayPath_Key, true);
- params.linkParameters(k_FindCheckedFeatures_Key, k_CheckedFeaturesName_Key, true);
-
- return params;
-}
-
-//------------------------------------------------------------------------------
-IFilter::UniquePointer ComputeGroupingDensityFilter::clone() const
-{
- return std::make_unique();
-}
-
-//------------------------------------------------------------------------------
-IFilter::VersionType ComputeGroupingDensityFilter::parametersVersion() const
-{
- return 1;
-}
-
-//------------------------------------------------------------------------------
-IFilter::PreflightResult ComputeGroupingDensityFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler,
- const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const
-{
- auto pParentIdsPath = filterArgs.value(k_ParentIdsPath_Key);
- auto pParentVolumesPath = filterArgs.value(k_ParentVolumesPath_Key);
- auto pContiguousNLPath = filterArgs.value(k_ContiguousNeighborListArrayPath_Key);
- auto pVolumesPath = filterArgs.value(k_VolumesArrayPath_Key);
- auto pGroupingDensitiesName = filterArgs.value(k_GroupingDensitiesName_Key);
-
- auto pUseNonContiguousNeighbors = filterArgs.value(k_UseNonContiguousNeighbors_Key);
- auto pNonContiguousNLPath = filterArgs.value(k_NonContiguousNeighborListArrayPath_Key);
- auto pFindCheckedFeatures = filterArgs.value(k_FindCheckedFeatures_Key);
- auto pCheckedFeaturesName = filterArgs.value(k_CheckedFeaturesName_Key);
-
- Result resultOutputActions;
- std::vector preflightUpdatedValues;
-
- auto* pParentAM = dataStructure.getDataAs(pParentVolumesPath.getParent());
- if(pParentAM == nullptr)
- {
- return MakePreflightErrorResult(-15670, fmt::format("Parent Volumes [{}] must be stored in an Attribute Matrix.", pParentVolumesPath.toString()));
- }
- {
- DataPath groupingDataPath = pParentVolumesPath.replaceName(pGroupingDensitiesName);
- auto createArrayAction = std::make_unique(nx::core::DataType::float32, pParentAM->getShape(), std::vector{1}, groupingDataPath);
- resultOutputActions.value().appendAction(std::move(createArrayAction));
- }
-
- auto* pFeatureAM = dataStructure.getDataAs(pVolumesPath.getParent());
- if(pFeatureAM == nullptr)
- {
- return MakePreflightErrorResult(-15671, fmt::format("Feature Volumes [{}] must be stored in an Attribute Matrix.", pVolumesPath.toString()));
- }
-
- if(pFindCheckedFeatures)
- {
- DataPath checkedFeaturesPath = pVolumesPath.replaceName(pCheckedFeaturesName);
- {
- auto createArrayAction = std::make_unique(nx::core::DataType::int32, pFeatureAM->getShape(), std::vector{1}, checkedFeaturesPath);
- resultOutputActions.value().appendAction(std::move(createArrayAction));
- }
- }
- else
- {
- {
- auto createArrayAction = std::make_unique(nx::core::DataType::int32, ShapeType{1}, ShapeType{1}, k_ThrowawayCheckedFeatures);
- resultOutputActions.value().appendAction(std::move(createArrayAction));
- }
- {
- auto removeAction = std::make_unique(k_ThrowawayCheckedFeatures);
- resultOutputActions.value().appendDeferredAction(std::move(removeAction));
- }
- }
-
- if(!pUseNonContiguousNeighbors)
- {
- {
- auto createArrayAction = std::make_unique(nx::core::DataType::int32, ShapeType{1}, k_ThrowawayNonContiguous);
- resultOutputActions.value().appendAction(std::move(createArrayAction));
- }
- {
- auto removeAction = std::make_unique(k_ThrowawayNonContiguous);
- resultOutputActions.value().appendDeferredAction(std::move(removeAction));
- }
- }
-
- preflightUpdatedValues.push_back({"WARNING: This filter is experimental in nature and has not had any testing, validation or verification. Use at your own risk"});
- resultOutputActions.warnings().push_back({-65432, "WARNING: This filter is experimental in nature and has not had any testing, validation or verification. Use at your own risk"});
-
- return {std::move(resultOutputActions), std::move(preflightUpdatedValues)};
-}
-
-//------------------------------------------------------------------------------
-Result<> ComputeGroupingDensityFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler,
- const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const
-{
- ComputeGroupingDensityInputValues inputValues;
-
- inputValues.ParentIdsPath = filterArgs.value(k_ParentIdsPath_Key);
- inputValues.ParentVolumesPath = filterArgs.value(k_ParentVolumesPath_Key);
- inputValues.ContiguousNLPath = filterArgs.value(k_ContiguousNeighborListArrayPath_Key);
- inputValues.VolumesPath = filterArgs.value(k_VolumesArrayPath_Key);
- inputValues.GroupingDensitiesPath = inputValues.ParentVolumesPath.replaceName(filterArgs.value(k_GroupingDensitiesName_Key));
-
- inputValues.UseNonContiguousNeighbors = filterArgs.value(k_UseNonContiguousNeighbors_Key);
- if(inputValues.UseNonContiguousNeighbors)
- {
- inputValues.NonContiguousNLPath = filterArgs.value(k_NonContiguousNeighborListArrayPath_Key);
- }
- else
- {
- inputValues.NonContiguousNLPath = k_ThrowawayNonContiguous;
- }
-
- inputValues.FindCheckedFeatures = filterArgs.value(k_FindCheckedFeatures_Key);
- if(inputValues.FindCheckedFeatures)
- {
- inputValues.CheckedFeaturesPath = inputValues.VolumesPath.replaceName(filterArgs.value(k_CheckedFeaturesName_Key));
- }
- else
- {
- inputValues.CheckedFeaturesPath = k_ThrowawayCheckedFeatures;
- }
-
- return ComputeGroupingDensity(dataStructure, messageHandler, shouldCancel, &inputValues)();
-}
-
-namespace
-{
-namespace SIMPL
-{
-constexpr StringLiteral k_CheckedFeaturesArrayNameKey = "CheckedFeaturesArrayName";
-constexpr StringLiteral k_ContiguousNeighborListArrayPathKey = "ContiguousNeighborListArrayPath";
-constexpr StringLiteral k_FindCheckedFeaturesKey = "FindCheckedFeatures";
-constexpr StringLiteral k_NonContiguousNeighborListArrayPathKey = "NonContiguousNeighborListArrayPath";
-constexpr StringLiteral k_ParentDensitiesArrayNameKey = "ParentDensitiesArrayName";
-constexpr StringLiteral k_ParentIdsArrayPathKey = "ParentIdsArrayPath";
-constexpr StringLiteral k_ParentVolumesArrayPathKey = "ParentVolumesArrayPath";
-constexpr StringLiteral k_UseNonContiguousNeighborsKey = "UseNonContiguousNeighbors";
-constexpr StringLiteral k_VolumesArrayPathKey = "VolumesArrayPath";
-} // namespace SIMPL
-} // namespace
-
-Result ComputeGroupingDensityFilter::FromSIMPLJson(const nlohmann::json& json)
-{
- Arguments args = ComputeGroupingDensityFilter().getDefaultArguments();
-
- std::vector> results;
-
- results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_CheckedFeaturesArrayNameKey, k_CheckedFeaturesName_Key));
- results.push_back(
- SIMPLConversion::ConvertParameter(args, json, SIMPL::k_ContiguousNeighborListArrayPathKey, k_ContiguousNeighborListArrayPath_Key));
- results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_FindCheckedFeaturesKey, k_FindCheckedFeatures_Key));
- results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_NonContiguousNeighborListArrayPathKey,
- k_NonContiguousNeighborListArrayPath_Key));
- results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_ParentDensitiesArrayNameKey, k_GroupingDensitiesName_Key));
- results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_ParentIdsArrayPathKey, k_ParentIdsPath_Key));
- results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_ParentVolumesArrayPathKey, k_ParentVolumesPath_Key));
- results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_UseNonContiguousNeighborsKey, k_UseNonContiguousNeighbors_Key));
- results.push_back(SIMPLConversion::ConvertParameter(args, json, SIMPL::k_VolumesArrayPathKey, k_VolumesArrayPath_Key));
-
- Result<> conversionResult = MergeResults(std::move(results));
-
- return ConvertResultTo(std::move(conversionResult), std::move(args));
-}
-} // namespace nx::core
diff --git a/src/SimplnxReview/SimplnxReviewLegacyUUIDMapping.hpp b/src/SimplnxReview/SimplnxReviewLegacyUUIDMapping.hpp
index d56f487..ffa4f3a 100644
--- a/src/SimplnxReview/SimplnxReviewLegacyUUIDMapping.hpp
+++ b/src/SimplnxReview/SimplnxReviewLegacyUUIDMapping.hpp
@@ -5,12 +5,12 @@
#include
/* clang-format off */
+#include "SimplnxReview/Filters/ComputeArrayNormFilter.hpp"
#include "SimplnxReview/Filters/GroupMicroTextureRegionsFilter.hpp"
#include "SimplnxReview/Filters/MergeColoniesFilter.hpp"
#include "SimplnxReview/Filters/ComputeSaltykovSizesFilter.hpp"
#include "SimplnxReview/Filters/ComputeMicroTextureRegionsFilter.hpp"
#include "SimplnxReview/Filters/ComputeLocalAverageCAxisMisalignmentsFilter.hpp"
-#include "SimplnxReview/Filters/ComputeGroupingDensityFilter.hpp"
// @@__HEADER__TOKEN__DO__NOT__DELETE__@@
@@ -22,12 +22,12 @@ namespace nx::core
static const AbstractPlugin::SIMPLMapType k_SIMPL_to_SimplnxReview
{
// syntax std::make_pair {Dream3d UUID , Dream3dnx UUID, {}}}, // dream3d-class-name
+ {nx::core::Uuid::FromString("5d0cd577-3e3e-57b8-a36d-b215b834251f").value(), {nx::core::FilterTraits::uuid, &ComputeArrayNormFilter::FromSIMPLJson}}, // FindNorm
{nx::core::Uuid::FromString("5e18a9e2-e342-56ac-a54e-3bd0ca8b9c53").value(), {nx::core::FilterTraits::uuid, &GroupMicroTextureRegionsFilter::FromSIMPLJson}}, // GroupMicroTextureRegions
{nx::core::Uuid::FromString("2c4a6d83-6a1b-56d8-9f65-9453b28845b9").value(), {nx::core::FilterTraits::uuid, &MergeColoniesFilter::FromSIMPLJson}}, // MergeColonies
{nx::core::Uuid::FromString("cc76cffe-81ad-5ece-be2a-ce127c5fa6d7").value(), {nx::core::FilterTraits::uuid, &ComputeSaltykovSizesFilter::FromSIMPLJson}}, // FindSaltykovSizes
{nx::core::Uuid::FromString("90f8e3b1-2460-5862-95a1-a9e06f5ee75e").value(), {nx::core::FilterTraits::uuid, &ComputeMicroTextureRegionsFilter::FromSIMPLJson}}, // FindMicroTextureRegions
{nx::core::Uuid::FromString("49b2dd47-bb29-50d4-a051-5bad9b6b9f80").value(), {nx::core::FilterTraits::uuid, &ComputeLocalAverageCAxisMisalignmentsFilter::FromSIMPLJson}}, // FindLocalAverageCAxisMisalignments
- {nx::core::Uuid::FromString("708be082-8b08-4db2-94be-52781ed4d53d").value(), {nx::core::FilterTraits::uuid, &ComputeGroupingDensityFilter::FromSIMPLJson}}, // FindGroupingDensity
// @@__MAP__UPDATE__TOKEN__DO__NOT__DELETE__@@
};