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__@@ };