Skip to content

Commit

Permalink
BUG: Add messaging when removing NeighborLists from the DataStructure.
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Jackson <[email protected]>
  • Loading branch information
imikejackson committed Apr 23, 2024
1 parent 1d80265 commit 6409474
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ Result<> RemoveFlaggedFeatures::operator()()

m_MessageHandler(IFilter::ProgressMessage{IFilter::Message::Type::Info, fmt::format("Stripping excess inactive objects from model...")});
DataPath featureGroupPath = m_InputValues->FlaggedFeaturesArrayPath.getParent();
if(!RemoveInactiveObjects(m_DataStructure, featureGroupPath, activeObjects, featureIds, flaggedFeatures->getNumberOfTuples()))
if(!RemoveInactiveObjects(m_DataStructure, featureGroupPath, activeObjects, featureIds, flaggedFeatures->getNumberOfTuples(), m_MessageHandler))
{
return MakeErrorResult(-45434, "The removal has failed!");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ Result<> ResampleImageGeom::operator()()

// NOW DO THE ACTUAL RENUMBERING and updating.
DataPath destFeatureIdsPath = destImagePath.createChildPath(srcCellDataAM.getName()).createChildPath(featureIdsArrayPath.getTargetName());
return Sampling::RenumberFeatures(m_DataStructure, destImagePath, destCellFeatureAMPath, featureIdsArrayPath, destFeatureIdsPath, m_ShouldCancel);
return Sampling::RenumberFeatures(m_DataStructure, destImagePath, destCellFeatureAMPath, featureIdsArrayPath, destFeatureIdsPath, m_MessageHandler, m_ShouldCancel);
}

return {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ Result<> CropImageGeometry::executeImpl(DataStructure& dataStructure, const Argu

// NOW DO THE ACTUAL RENUMBERING and updating.
DataPath destFeatureIdsPath = destImagePath.createChildPath(srcCellDataAM.getName()).createChildPath(featureIdsArrayPath.getTargetName());
return Sampling::RenumberFeatures(dataStructure, destImagePath, destCellFeatureAMPath, featureIdsArrayPath, destFeatureIdsPath, shouldCancel);
return Sampling::RenumberFeatures(dataStructure, destImagePath, destCellFeatureAMPath, featureIdsArrayPath, destFeatureIdsPath, messageHandler, shouldCancel);
}

// The deferred actions will take care of removing the original and renaming the output if
Expand Down
49 changes: 41 additions & 8 deletions src/Plugins/SimplnxCore/src/SimplnxCore/Filters/MinNeighbors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "simplnx/DataStructure/DataArray.hpp"
#include "simplnx/DataStructure/Geometry/ImageGeom.hpp"
#include "simplnx/Filter/Actions/DeleteDataAction.hpp"
#include "simplnx/Parameters/ArraySelectionParameter.hpp"
#include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp"
#include "simplnx/Parameters/BoolParameter.hpp"
Expand All @@ -21,6 +22,8 @@ namespace
constexpr int64 k_TupleCountInvalidError = -250;
constexpr int64 k_MissingFeaturePhasesError = -251;
constexpr int32 k_InconsistentTupleCount = -252;
constexpr int32 k_NeighborListRemoval = -5558;
constexpr int32 k_FetchChildArrayError = -5559;

void assignBadPoints(DataStructure& data, const Arguments& args, const std::atomic_bool& shouldCancel)
{
Expand Down Expand Up @@ -401,12 +404,42 @@ IFilter::PreflightResult MinNeighbors::preflightImpl(const DataStructure& dataSt
// Feature Data is going to be modified
nx::core::AppendDataObjectModifications(dataStructure, resultOutputActions.value().modifiedActions, numNeighborsPath.getParent(), {});

// This section gives a warning to the user about NeighborLists possibly being removed
{
DataPath featureGroupDataPath = numNeighborsPath.getParent();

// Throw a warning to inform the user that the neighbor list arrays could be deleted by this filter
std::string ss = fmt::format("If this filter modifies the Cell Level Array '{}', all arrays of type NeighborList will be deleted from the feature data group '{}'. These arrays are:\n",
featureIdsPath.toString(), featureGroupDataPath.toString());

auto result = nx::core::GetAllChildDataPaths(dataStructure, featureGroupDataPath, DataObject::Type::NeighborList);
if(!result.has_value())
{
return {nonstd::make_unexpected(
std::vector<Error>{Error{k_FetchChildArrayError, fmt::format("Errors were encountered trying to retrieve the neighbor list children of group '{}'", featureGroupDataPath.toString())}})};
}
std::vector<DataPath> featureNeighborListArrays = result.value();
for(const auto& featureNeighborList : featureNeighborListArrays)
{
ss.append(" " + featureNeighborList.toString() + "\n");
auto action = std::make_unique<DeleteDataAction>(featureNeighborList);
resultOutputActions.value().actions.emplace_back(std::move(action));
}

// Inform users that the following arrays are going to be modified in place
// Feature Data is going to be modified
nx::core::AppendDataObjectModifications(dataStructure, resultOutputActions.value().modifiedActions, featureGroupDataPath, {});

resultOutputActions.warnings().push_back(Warning{k_NeighborListRemoval, ss});
}

// Return both the resultOutputActions and the preflightUpdatedValues via std::move()
return {std::move(resultOutputActions), std::move(preflightUpdatedValues)};
}

//------------------------------------------------------------------------------
Result<> MinNeighbors::executeImpl(DataStructure& data, const Arguments& args, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel) const
Result<> MinNeighbors::executeImpl(DataStructure& dataStructure, const Arguments& args, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler,
const std::atomic_bool& shouldCancel) const
{
auto featurePhasesPath = args.value<DataPath>(k_FeaturePhasesPath_Key);
auto applyToSinglePhase = args.value<bool>(k_ApplyToSinglePhase_Key);
Expand All @@ -418,7 +451,7 @@ Result<> MinNeighbors::executeImpl(DataStructure& data, const Arguments& args, c
// we don't have access to the data yet
if(applyToSinglePhase)
{
auto& featurePhasesArray = data.getDataRefAs<Int32Array>(featurePhasesPath);
auto& featurePhasesArray = dataStructure.getDataRefAs<Int32Array>(featurePhasesPath);
auto& featurePhases = featurePhasesArray.getDataStoreRef();

usize numFeatures = featurePhasesArray.getNumberOfTuples();
Expand All @@ -439,27 +472,27 @@ Result<> MinNeighbors::executeImpl(DataStructure& data, const Arguments& args, c
}
}

auto activeObjectsResult = mergeContainedFeatures(data, args, shouldCancel);
auto activeObjectsResult = mergeContainedFeatures(dataStructure, args, shouldCancel);
if(!activeObjectsResult.has_value())
{
return {nonstd::make_unexpected(std::vector<Error>{activeObjectsResult.error()})};
}

auto cellDataAttrMatrix = args.value<DataPath>(MinNeighbors::k_CellDataAttributeMatrixPath_Key);
auto result = nx::core::GetAllChildDataPaths(data, cellDataAttrMatrix, DataObject::Type::DataArray);
auto result = nx::core::GetAllChildDataPaths(dataStructure, cellDataAttrMatrix, DataObject::Type::DataArray);
if(!result.has_value())
{
return MakeErrorResult(-5556, fmt::format("Error fetching all Data Arrays from Group '{}'", cellDataAttrMatrix.toString()));
}

// Run the algorithm.
assignBadPoints(data, args, shouldCancel);
assignBadPoints(dataStructure, args, shouldCancel);

auto featureIdsPath = args.value<DataPath>(MinNeighbors::k_FeatureIdsPath_Key);
auto& featureIdsArray = data.getDataRefAs<Int32Array>(featureIdsPath);
auto& featureIdsArray = dataStructure.getDataRefAs<Int32Array>(featureIdsPath);

auto numNeighborsPath = args.value<DataPath>(MinNeighbors::k_NumNeighborsPath_Key);
auto& numNeighborsArray = data.getDataRefAs<Int32Array>(numNeighborsPath);
auto& numNeighborsArray = dataStructure.getDataRefAs<Int32Array>(numNeighborsPath);

DataPath cellFeatureGroupPath = numNeighborsPath.getParent();
size_t currentFeatureCount = numNeighborsArray.getNumberOfTuples();
Expand All @@ -473,7 +506,7 @@ Result<> MinNeighbors::executeImpl(DataStructure& data, const Arguments& args, c
std::string message = fmt::format("Feature Count Changed: Previous: {} New: {}", currentFeatureCount, count);
messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, message});

nx::core::RemoveInactiveObjects(data, cellFeatureGroupPath, activeObjects, featureIdsArray, currentFeatureCount);
nx::core::RemoveInactiveObjects(dataStructure, cellFeatureGroupPath, activeObjects, featureIdsArray, currentFeatureCount, messageHandler);

return {};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ IFilter::UniquePointer RemoveMinimumSizeFeaturesFilter::clone() const
return std::make_unique<RemoveMinimumSizeFeaturesFilter>();
}

IFilter::PreflightResult RemoveMinimumSizeFeaturesFilter::preflightImpl(const DataStructure& data, const Arguments& args, const MessageHandler& messageHandler,
IFilter::PreflightResult RemoveMinimumSizeFeaturesFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& args, const MessageHandler& messageHandler,
const std::atomic_bool& shouldCancel) const
{
auto featurePhasesPath = args.value<DataPath>(k_FeaturePhasesPath_Key);
Expand All @@ -336,12 +336,12 @@ IFilter::PreflightResult RemoveMinimumSizeFeaturesFilter::preflightImpl(const Da
return {nonstd::make_unexpected(std::vector<Error>{Error{-k_BadMinAllowedFeatureSize, ss}})};
}

const FeatureIdsArrayType* featureIdsPtr = data.getDataAs<FeatureIdsArrayType>(featureIdsPath);
const FeatureIdsArrayType* featureIdsPtr = dataStructure.getDataAs<FeatureIdsArrayType>(featureIdsPath);
if(featureIdsPtr == nullptr)
{
return {nonstd::make_unexpected(std::vector<Error>{Error{k_BadNumCellsPath, "FeatureIds not provided as an Int32 Array."}})};
}
const NumCellsArrayType* numCellsPtr = data.getDataAs<NumCellsArrayType>(numCellsPath);
const NumCellsArrayType* numCellsPtr = dataStructure.getDataAs<NumCellsArrayType>(numCellsPath);
if(numCellsPtr == nullptr)
{
return {nonstd::make_unexpected(std::vector<Error>{Error{k_BadNumCellsPath, "Num Cells not provided as an Int32 Array."}})};
Expand All @@ -350,19 +350,19 @@ IFilter::PreflightResult RemoveMinimumSizeFeaturesFilter::preflightImpl(const Da

if(applyToSinglePhase)
{
const PhasesArrayType* featurePhasesPtr = data.getDataAs<PhasesArrayType>(featurePhasesPath);
const PhasesArrayType::store_type* featurePhases = nullptr;
const PhasesArrayType* featurePhasesPtr = dataStructure.getDataAs<PhasesArrayType>(featurePhasesPath);
// const PhasesArrayType::store_type* featurePhases = nullptr;
if(featurePhasesPtr != nullptr)
{
dataArrayPaths.push_back(featurePhasesPath);
featurePhases = featurePhasesPtr->getDataStore();
// featurePhases = featurePhasesPtr->getDataStore();
}
}

data.validateNumberOfTuples(dataArrayPaths);
dataStructure.validateNumberOfTuples(dataArrayPaths);

DataPath featureGroupDataPath = numCellsPath.getParent();
const BaseGroup* featureDataGroup = data.getDataAs<BaseGroup>(featureGroupDataPath);
const BaseGroup* featureDataGroup = dataStructure.getDataAs<BaseGroup>(featureGroupDataPath);
if(nullptr == featureDataGroup)
{
return {nonstd::make_unexpected(std::vector<Error>{Error{k_ParentlessPathError, "The provided NumCells DataPath does not have a parent."}})};
Expand All @@ -372,30 +372,32 @@ IFilter::PreflightResult RemoveMinimumSizeFeaturesFilter::preflightImpl(const Da
nx::core::Result<OutputActions> resultOutputActions;
std::vector<PreflightValue> preflightUpdatedValues;

// Throw a warning to inform the user that the neighbor list arrays could be deleted by this filter
std::string ss = fmt::format("If this filter modifies the Cell Level Array '{}', all arrays of type NeighborList will be deleted from the feature data group '{}'. These arrays are:\n",
featureIdsPath.toString(), featureGroupDataPath.toString());

auto result = nx::core::GetAllChildDataPaths(data, featureGroupDataPath, DataObject::Type::NeighborList);
if(!result.has_value())
{
return {nonstd::make_unexpected(
std::vector<Error>{Error{k_FetchChildArrayError, fmt::format("Errors were encountered trying to retrieve the neighbor list children of group '{}'", featureGroupDataPath.toString())}})};
}
std::vector<DataPath> featureNeighborListArrays = result.value();
for(const auto& featureNeighborList : featureNeighborListArrays)
// This section gives a warning to the user about NeighborLists possibly being removed
{
ss.append(" " + featureNeighborList.toString() + "\n");
auto action = std::make_unique<DeleteDataAction>(featureNeighborList);
resultOutputActions.value().actions.emplace_back(std::move(action));
}
// Throw a warning to inform the user that the neighbor list arrays could be deleted by this filter
std::string ss = fmt::format("If this filter modifies the Cell Level Array '{}', all arrays of type NeighborList will be deleted from the feature data group '{}'. These arrays are:\n",
featureIdsPath.toString(), featureGroupDataPath.toString());

// Inform users that the following arrays are going to be modified in place
// Feature Data is going to be modified
nx::core::AppendDataObjectModifications(data, resultOutputActions.value().modifiedActions, featureGroupDataPath, {});
auto result = nx::core::GetAllChildDataPaths(dataStructure, featureGroupDataPath, DataObject::Type::NeighborList);
if(!result.has_value())
{
return {nonstd::make_unexpected(
std::vector<Error>{Error{k_FetchChildArrayError, fmt::format("Errors were encountered trying to retrieve the neighbor list children of group '{}'", featureGroupDataPath.toString())}})};
}
std::vector<DataPath> featureNeighborListArrays = result.value();
for(const auto& featureNeighborList : featureNeighborListArrays)
{
ss.append(" " + featureNeighborList.toString() + "\n");
auto action = std::make_unique<DeleteDataAction>(featureNeighborList);
resultOutputActions.value().actions.emplace_back(std::move(action));
}

resultOutputActions.warnings().push_back(Warning{k_NeighborListRemoval, ss});
// Inform users that the following arrays are going to be modified in place
// Feature Data is going to be modified
nx::core::AppendDataObjectModifications(dataStructure, resultOutputActions.value().modifiedActions, featureGroupDataPath, {});

resultOutputActions.warnings().push_back(Warning{k_NeighborListRemoval, ss});
}
// Return both the resultOutputActions and the preflightUpdatedValues via std::move()
return {std::move(resultOutputActions), std::move(preflightUpdatedValues)};
}
Expand Down Expand Up @@ -466,7 +468,7 @@ Result<> RemoveMinimumSizeFeaturesFilter::executeImpl(DataStructure& dataStructu
std::string message = fmt::format("Feature Count Changed: Previous: {} New: {}", currentFeatureCount, count);
messageHandler(nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Info, message});

nx::core::RemoveInactiveObjects(dataStructure, cellFeatureGroupPath, activeObjects, featureIdsArrayRef, currentFeatureCount);
nx::core::RemoveInactiveObjects(dataStructure, cellFeatureGroupPath, activeObjects, featureIdsArrayRef, currentFeatureCount, messageHandler);

return {};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,12 @@ class SIMPLNXCORE_EXPORT RemoveMinimumSizeFeaturesFilter : public IFilter
protected:
/**
* @brief
* @param data
* @param dataStructure
* @param args
* @param messageHandler
* @return PreflightResult
*/
PreflightResult preflightImpl(const DataStructure& data, const Arguments& args, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel) const override;
PreflightResult preflightImpl(const DataStructure& dataStructure, const Arguments& args, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel) const override;

/**
* @brief
Expand Down
5 changes: 4 additions & 1 deletion src/simplnx/Utilities/DataGroupUtilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

namespace nx::core
{
bool RemoveInactiveObjects(DataStructure& dataStructure, const DataPath& featureDataGroupPath, const std::vector<bool>& activeObjects, Int32Array& cellFeatureIds, size_t currentFeatureCount)
bool RemoveInactiveObjects(DataStructure& dataStructure, const DataPath& featureDataGroupPath, const std::vector<bool>& activeObjects, Int32Array& cellFeatureIds, size_t currentFeatureCount,
const IFilter::MessageHandler& messageHandler)
{
bool acceptableMatrix = true;

Expand Down Expand Up @@ -97,6 +98,8 @@ bool RemoveInactiveObjects(DataStructure& dataStructure, const DataPath& feature
std::vector<DataPath> neighborListDataPaths = result.value();
for(const auto& neighborListDataPath : neighborListDataPaths)
{
messageHandler(
nx::core::IFilter::Message{nx::core::IFilter::Message::Type::Warning, fmt::format("NeighborList '{}' was removed from the DataStructure.", neighborListDataPath.toString())});
dataStructure.removeData(neighborListDataPath);
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/simplnx/Utilities/DataGroupUtilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "simplnx/DataStructure/DataPath.hpp"
#include "simplnx/DataStructure/DataStructure.hpp"
#include "simplnx/DataStructure/IDataArray.hpp"
#include "simplnx/Filter/IFilter.hpp"
#include "simplnx/simplnx_export.hpp"

#include <memory>
Expand All @@ -19,10 +20,11 @@ namespace nx::core
* @param featureDataGroupPath
* @param activeObjects
* @param cellFeatureIds
* @param messageHandler
* @return
*/
SIMPLNX_EXPORT bool RemoveInactiveObjects(DataStructure& dataStructure, const DataPath& featureDataGroupPath, const std::vector<bool>& activeObjects, Int32Array& cellFeatureIds,
size_t currentFeatureCount);
size_t currentFeatureCount, const IFilter::MessageHandler& messageHandler);

/**
* @brief This function will gather all of the sibling DataArrays to the input DataPath, then filter out all the 'IgnoredDataPaths`
Expand Down
4 changes: 2 additions & 2 deletions src/simplnx/Utilities/SamplingUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace nx::core
namespace Sampling
{
inline Result<> RenumberFeatures(DataStructure& dataStructure, const DataPath& newGeomPath, const DataPath& destCellFeatAttributeMatrixPath, const DataPath& featureIdsArrayPath,
const DataPath& destFeatureIdsArrayPath, const std::atomic_bool& shouldCancel = false)
const DataPath& destFeatureIdsArrayPath, const IFilter::MessageHandler& messageHandler, const std::atomic_bool& shouldCancel = false)
{
auto& destImageGeom = dataStructure.getDataRefAs<ImageGeom>(newGeomPath);
// This just sanity checks to make sure there were existing features before the cropping
Expand Down Expand Up @@ -58,7 +58,7 @@ inline Result<> RenumberFeatures(DataStructure& dataStructure, const DataPath& n
}
}

if(!RemoveInactiveObjects(dataStructure, destCellFeatAttributeMatrixPath, activeObjects, destFeatureIdsRef, totalFeatures))
if(!RemoveInactiveObjects(dataStructure, destCellFeatAttributeMatrixPath, activeObjects, destFeatureIdsRef, totalFeatures, messageHandler))
{
std::string ss = fmt::format("An error occurred while trying to remove the inactive objects from Attribute Matrix '{}'", destCellFeatAttributeMatrixPath.toString());
return MakeErrorResult(-606, ss);
Expand Down

0 comments on commit 6409474

Please sign in to comment.