Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/Plugins/SimplnxCore/docs/ComputeFeaturePhasesFilter.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ Generic (Misc)

## Description

This **Filter** determines the **Ensemble** of each **Feature** by querying the **Ensemble** of the **Elements** that belong to the **Feature**. Note that it is assumed that all **Elements** belonging to a **Feature** are of the same **Feature**, and thus any **Element** can be used to determine the **Ensemble** of the **Feature** that owns that **Element**.
This **Filter** determines the **Ensemble** (phase) of each **Feature** by iterating over all **Elements** and writing `featurePhases[featureId] = cellPhase` for each cell. When all cells of a **Feature** share the same phase the result is unambiguous. When they differ, the last cell encountered (by ascending index order) wins and a warning is emitted listing up to 15 affected **Feature** IDs.

**Background feature:** Cells with `featureId == 0` are skipped. `featurePhases[0]` is never written and will always be `0`; downstream filters should not rely on its value.

**Errors:** The filter halts with an error if any cell phase value is negative, or if the **Cell Phases** and **Feature Ids** arrays have different tuple counts.

% Auto generated parameter table will be inserted here

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
#include "ComputeFeaturePhases.hpp"

#include "simplnx/DataStructure/AttributeMatrix.hpp"
#include "simplnx/DataStructure/DataArray.hpp"
#include "simplnx/Utilities/DataArrayUtilities.hpp"

#include <map>
#include <set>

using namespace nx::core;

// -----------------------------------------------------------------------------
Expand All @@ -24,23 +20,29 @@ ComputeFeaturePhases::~ComputeFeaturePhases() noexcept = default;
// -----------------------------------------------------------------------------
Result<> ComputeFeaturePhases::operator()()
{
auto featurePhasesArrayPath = m_InputValues->CellFeaturesAttributeMatrixPath.createChildPath(m_InputValues->FeaturePhasesArrayName);
const auto featurePhasesArrayPath = m_InputValues->CellFeaturesAttributeMatrixPath.createChildPath(m_InputValues->FeaturePhasesArrayName);

const auto& cellPhases = m_DataStructure.getDataAs<Int32Array>(m_InputValues->CellPhasesArrayPath)->getDataStoreRef();
const auto& cellPhasesStore = m_DataStructure.getDataRefAs<Int32Array>(m_InputValues->CellPhasesArrayPath).getDataStoreRef();
const auto& featureIdsArray = m_DataStructure.getDataRefAs<Int32Array>(m_InputValues->FeatureIdsPath);
const auto& featureIds = featureIdsArray.getDataStoreRef();
auto& featurePhases = m_DataStructure.getDataAs<Int32Array>(featurePhasesArrayPath)->getDataStoreRef();
const auto& featureIdsStore = featureIdsArray.getDataStoreRef();
auto& featurePhasesStore = m_DataStructure.getDataRefAs<Int32Array>(featurePhasesArrayPath).getDataStoreRef();

// Validate the featurePhases array is the proper size
// Validate the featurePhases array sizing matches feature index values in featureIds (bounds check) and feature ids are all positive
auto validateNumFeatResult = ValidateFeatureIdsToFeatureAttributeMatrixIndexing(m_DataStructure, m_InputValues->CellFeaturesAttributeMatrixPath, featureIdsArray, false, m_MessageHandler);
if(validateNumFeatResult.invalid())
{
return validateNumFeatResult;
}

usize totalPoints = featureIds.getNumberOfTuples();
std::map<int32, int32> featureMap;
std::set<int32> warnFeatures;
const usize totalPoints = featureIdsStore.getNumberOfTuples();
if(totalPoints != cellPhasesStore.getNumberOfTuples())
{
return MakeErrorResult(-61860, "Size mismatch between cell feature indices and cell phases arrays.");
}

const usize numFeatures = featurePhasesStore.getNumberOfTuples();
std::vector<int32> initialFeaturePhase(numFeatures, -1);
std::vector<bool> warnFeature(numFeatures, false);

for(usize i = 0; i < totalPoints; i++)
{
Expand All @@ -49,29 +51,60 @@ Result<> ComputeFeaturePhases::operator()()
return {};
}

int32 gnum = featureIds[i];
featureMap.insert({gnum, cellPhases[i]});
const int32 featureId = featureIdsStore.getValue(i);
// Ignore 0, invalid feature
if(featureId == 0)
{
continue;
}

const int32 currentPhaseId = cellPhasesStore.getValue(i);

if(currentPhaseId < 0)
{
return MakeErrorResult(-61861, fmt::format("Cell phases contains a negative value. Index: {} | Value: {}", i, currentPhaseId));
}

int32 curPhaseVal = featureMap[gnum];
if(curPhaseVal != cellPhases[i])
int32 storedPhaseId = initialFeaturePhase[featureId];
if(storedPhaseId == -1)
{
warnFeatures.insert(gnum);
initialFeaturePhase[featureId] = currentPhaseId;
}
featurePhases[gnum] = cellPhases[i];
else if(storedPhaseId != currentPhaseId)
{
warnFeature[featureId] = true;
}

featurePhasesStore.setValue(static_cast<usize>(featureId), currentPhaseId);
}

Result<> result;
if(!warnFeatures.empty())

std::string warnStr = "Elements from some features did not all have the same phase ID. The last phase ID copied into each feature will be used. Affected Phase Features: ";
usize count = 0;
// Ignore 0 it is not a valid feature
for(usize i = 1; i < numFeatures; i++)
{
std::string warnStr = "Elements from some features did not all have the same phase ID. The last phase ID copied into each feature will be used. Effected Phase Features: ";
usize position = 0;
for(auto value : warnFeatures)
if(warnFeature[i])
{
warnStr.append(std::to_string(value));
if(++position != warnFeatures.size())
if(count < 15)
{
warnStr.append(", ");
if(count > 0)
{
warnStr.append(", ");
}
warnStr.append(std::to_string(i));
}
count++;
}
}

if(count != 0)
{
if(count > 15)
{
usize remainder = count - 15;
warnStr.append(fmt::format(", and {} more {}", remainder, remainder == 1 ? "occurrence" : "occurrences"));
}
result.warnings().push_back(Warning{-500, std::move(warnStr)});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,6 @@
#include "simplnx/Parameters/AttributeMatrixSelectionParameter.hpp"
#include "simplnx/Parameters/DataObjectNameParameter.hpp"

/**
* This is example code to put in the Execute Method of the filter.
ComputeFeaturePhasesInputValues inputValues;
inputValues.CellFeaturesAttributeMatrixPath = filterArgs.value<AttributeMatrixSelectionParameter::ValueType>(cell_features_attribute_matrix_path);
inputValues.CellPhasesArrayPath = filterArgs.value<ArraySelectionParameter::ValueType>(cell_phases_array_path);
inputValues.FeatureIdsPath = filterArgs.value<ArraySelectionParameter::ValueType>(feature_ids_path);
inputValues.FeaturePhasesArrayName = filterArgs.value<DataObjectNameParameter::ValueType>(feature_phases_array_name);
return ComputeFeaturePhases(dataStructure, messageHandler, shouldCancel, &inputValues)();

*/

namespace nx::core
{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ IFilter::PreflightResult ComputeFeaturePhasesFilter::preflightImpl(const DataStr
auto pCellFeatureAMPathValue = filterArgs.value<DataPath>(k_CellFeaturesAttributeMatrixPath_Key);
auto pFeaturePhasesArrayPathValue = pCellFeatureAMPathValue.createChildPath(filterArgs.value<std::string>(k_FeaturePhasesArrayName_Key));

nx::core::Result<OutputActions> resultOutputActions;
Result<OutputActions> resultOutputActions;

const auto& cellFeatData = dataStructure.getDataRefAs<AttributeMatrix>(pCellFeatureAMPathValue);

Expand Down
Loading
Loading