Skip to content

Commit

Permalink
FIlter complete - unit test pending
Browse files Browse the repository at this point in the history
  • Loading branch information
nyoungbq authored and imikejackson committed Jul 3, 2023
1 parent f5aca08 commit ea43fe6
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 35 deletions.
69 changes: 69 additions & 0 deletions src/Plugins/OrientationAnalysis/docs/MergeColoniesFilter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Merge Colonies #

## Group (Subgroup) ##

Reconstruction (Grouping)

## Description ##

This **Filter** groups neighboring **Features** that have a *special* misorientation that is associated with *alpha* variants that transformed from the same *beta* grain in titanium. The algorithm for grouping the **Features** is analogous to the algorithm for segmenting the **Features**, except the average orientation of the **Features** are used instead of the orientations of the individual **Elements** and the criterion for grouping is specific to the *alpha-beta transformation*. The user can specify a tolerance on both the *axis* and the *angle* that defines the misorientation relationship (i.e., a tolerance of 1 degree for both tolerances would allow the neighboring **Features** to be grouped if their misorientation was between 59-61 degrees about an axis within 1 degree of a2, as given by the 3rd *special* misorientation below).

The list of *special* misorientations can be found in the paper by Germain et al.<sup>1</sup> and are listed here:

| Angle | Axis |
|------|------|
| 0 | Identity |
| 10.529 | c = <0001> |
| 60 | a2 = <-12-10> |
| 60.832 | d1 at 80.97 degrees from c in the plane of (d3,c) |
| 63.262 | d2 at 72.73 degrees from c in the plane of (a2,c) |
| 90 | d3 at 5.26 degrees from a2 in the basal plane |

## Parameters ##

| Name | Type | Description |
|------|------| ----------- |
| Use Seed | bool | Whether a seed shouold be used for random generation |
| Seed | uint64 | This is the value fed into the random generator |
| Axis Tolerance (Degrees) | float32 | Tolerance allowed when comparing the axis part of the axis-angle representation of the misorientation to the *special* misorientations listed above |
| Angle Tolerance (Degrees) | float32 | Tolerance allowed when comparing the angle part of the axis-angle representation of the misorientation to the *special* misorientations listed above |
| Use Non-Contiguous Neighbors | bool | Whether to use a non-contiguous neighbor list during the merging process |

## Required Geometry ##

Not Applicable

## Required Objects ##

| Kind | Default Name | Type | Component Dimensions | Description |
|------|--------------|------|----------------------|-------------|
| **Feature Attribute Array** | NonContiguousNeighbors | Int32NeighborList | (1) | List of non-contiguous neighbors for each **Feature**. Only needed if *Use Non-Contiguous Neighbors* is checked |
| **Feature Attribute Array** | NeighborList | Int32NeighborList | (1) | List of neighbors for each **Feature** |
| **Element Attribute Array** | FeatureIds | int32 | (1) | Specifies to which **Feature** each **Element** belongs |
| **Element Attribute Array** | Phases | int32 | (1) | Specifies to which **Ensemble** each **Element** belongs |
| **Feature Attribute Array** | Phases | int32 | (1) | Specifies to which **Ensemble** each **Feature** belongs |
| **Feature Attribute Array** | AvgQuats | float32 | (4) | Specifies the average orientation of the **Feature** in quaternion representation |
| **Ensemble Attribute Array** | CrystalStructures | uint32 | (1) | Enumeration representing the crystal structure for each **Ensemble** |

## Created Objects ##

| Kind | Default Name | Type | Component Dimensions | Description |
|------|--------------|------|----------------------|-------------|
| **Element Attribute Array** | ParentIds | int32 | (1) | Specifies to which *parent* each **Element** belongs |
| **Attribute Matrix** | NewFeatureData | Feature | N/A | Created **Feature Attribute Matrix** name |
| **Feature Attribute Array** | ParentIds | int32 | (1) | Specifies to which *parent* each **Feature** belongs |
| **Feature Attribute Array** | Active | bool | (1) | Specifies if the **Feature** is still in the sample (*true* if the **Feature** is in the sample and *false* if it is not). At the end of the **Filter**, all **Features** will be *Active* |

## References ##

[1] L. Germain, N. Gey and M. Humbert, Reliability of reconstructed Beta orientation maps in titanium alloys, Ultramicrscopy, 2007, 1129-1135.

## Example Pipelines ##

## License & Copyright ##

Please see the description file distributed with this **Plugin**

## DREAM.3D Mailing Lists ##

If you need more help with a **Filter**, please consider asking your question on the [DREAM.3D Users Google group!](https://groups.google.com/forum/?hl=en#!forum/dream3d-users)
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,7 @@ Result<> MergeColonies::operator()()
// Generate all the numbers up front
const int32 rangeMin = 1;
const int32 rangeMax = numParents - 1;
std::mt19937::result_type seed = static_cast<std::mt19937::result_type>(std::chrono::steady_clock::now().time_since_epoch().count());
std::mt19937 generator(seed); // Standard mersenne_twister_engine seeded with milliseconds
std::mt19937 generator(m_InputValues->SeedValue); // Standard mersenne_twister_engine seeded
std::uniform_int_distribution<int32> distribution(rangeMin, rangeMax);

std::vector<int32> pid(numParents);
Expand Down Expand Up @@ -245,15 +244,16 @@ int32 MergeColonies::getSeed(int32 newFid)
{
usize numFeatures = m_FeaturePhases.getNumberOfTuples();

SIMPL_RANDOMNG_NEW();
std::mt19937 generator(m_InputValues->SeedValue); // Standard mersenne_twister_engine seeded
std::uniform_real_distribution<float32> distribution(0, 1);
int32 seed = -1;
int32 randFeature = 0;

// Precalculate some constants
usize totalFMinus1 = numFeatures - 1;

usize counter = 0;
randFeature = int32(float32(rg.genrand_res53()) * float32(totalFMinus1));
randFeature = int32(distribution(generator) * float32(totalFMinus1));
while(seed == -1 && counter < numFeatures)
{
if(randFeature > totalFMinus1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct ORIENTATIONANALYSIS_EXPORT MergeColoniesInputValues
DataPath CellFeatureAMPath;
DataPath FeatureParentIdsPath;
DataPath ActivePath;
uint64 SeedValue;
bool RandomizeParentIds = true;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
#include "OrientationAnalysis/Filters/Algorithms/MergeColonies.hpp"

#include "complex/DataStructure/DataPath.hpp"
#include "complex/Filter/Actions/EmptyAction.hpp"
#include "complex/Parameters/ArrayCreationParameter.hpp"
#include "complex/Filter/Actions/CreateArrayAction.hpp"
#include "complex/Filter/Actions/CreateAttributeMatrixAction.hpp"
#include "complex/Parameters/ArraySelectionParameter.hpp"
#include "complex/Parameters/BoolParameter.hpp"
#include "complex/Parameters/DataGroupCreationParameter.hpp"
#include "complex/Parameters/DataObjectNameParameter.hpp"
#include "complex/Parameters/NeighborListSelectionParameter.hpp"
#include "complex/Parameters/NumberParameter.hpp"

#include <random>

using namespace complex;

namespace complex
Expand Down Expand Up @@ -50,6 +54,10 @@ Parameters MergeColoniesFilter::parameters() const
Parameters params;

// Create the parameter descriptors that are needed for this filter
params.insertSeparator(Parameters::Separator{"Optional Variables"});
params.insertLinkableParameter(std::make_unique<BoolParameter>(k_UseSeed_Key, "Use Seed for Random Generation", "When true the user will be able to put in a seed for random generation", false));
params.insert(std::make_unique<NumberParameter<uint64>>(k_SeedValue_Key, "Seed", "The seed fed into the random generator", std::mt19937::default_seed));

params.insertSeparator(Parameters::Separator{"Input Parameters"});
params.insertLinkableParameter(std::make_unique<BoolParameter>(k_UseNonContiguousNeighbors_Key, "Use Non-Contiguous Neighbors", "", false));
params.insert(std::make_unique<Float32Parameter>(k_AxisTolerance_Key, "Axis Tolerance (Degrees)", "", 0.0f));
Expand All @@ -68,23 +76,24 @@ Parameters MergeColoniesFilter::parameters() const
params.insertSeparator(Parameters::Separator{"Required Element Data"});
params.insert(std::make_unique<ArraySelectionParameter>(k_FeatureIdsArrayPath_Key, "Feature Ids", "", DataPath{}, ArraySelectionParameter::AllowedTypes{DataType::int32},
ArraySelectionParameter::AllowedComponentShapes{{1}}));
params.insert(std::make_unique<ArraySelectionParameter>(k_CellPhasesArrayPath_Key, "Phases", "", DataPath{}, ArraySelectionParameter::AllowedTypes{DataType::int32},
params.insert(std::make_unique<ArraySelectionParameter>(k_CellPhasesArrayPath_Key, "Cell Phases", "", DataPath{}, ArraySelectionParameter::AllowedTypes{DataType::int32},
ArraySelectionParameter::AllowedComponentShapes{{1}}));

params.insertSeparator(Parameters::Separator{"Required Ensemble Data"});
params.insert(std::make_unique<ArraySelectionParameter>(k_CrystalStructuresArrayPath_Key, "Crystal Structures", "", DataPath{}, ArraySelectionParameter::AllowedTypes{DataType::uint32},
ArraySelectionParameter::AllowedComponentShapes{{1}}));

params.insertSeparator(Parameters::Separator{"Created Element Data"});
params.insert(std::make_unique<ArrayCreationParameter>(k_CellParentIdsArrayName_Key, "Parent Ids", "", DataPath{}));
params.insert(std::make_unique<DataObjectNameParameter>(k_CellParentIdsArrayName_Key, "Cell Parent Ids", "", "Cell Parent Ids"));

params.insertSeparator(Parameters::Separator{"Created Feature Data"});
params.insert(std::make_unique<ArrayCreationParameter>(k_NewCellFeatureAttributeMatrixName_Key, "Feature Attribute Matrix", "", DataPath{}));
params.insert(std::make_unique<ArrayCreationParameter>(k_FeatureParentIdsArrayName_Key, "Parent Ids", "", DataPath{}));
params.insert(std::make_unique<ArrayCreationParameter>(k_ActiveArrayName_Key, "Active", "", DataPath{}));
params.insert(std::make_unique<DataGroupCreationParameter>(k_NewCellFeatureAttributeMatrixName_Key, "Feature Attribute Matrix", "", DataPath{}));
params.insert(std::make_unique<DataObjectNameParameter>(k_FeatureParentIdsArrayName_Key, "Feature Parent Ids", "", "Feature Parent Ids"));
params.insert(std::make_unique<DataObjectNameParameter>(k_ActiveArrayName_Key, "Active", "", "Active Features"));

// Associate the Linkable Parameter(s) to the children parameters that they control
params.linkParameters(k_UseNonContiguousNeighbors_Key, k_NonContiguousNeighborListArrayPath_Key, true);
params.linkParameters(k_UseSeed_Key, k_SeedValue_Key, true);

return params;
}
Expand All @@ -99,20 +108,48 @@ IFilter::UniquePointer MergeColoniesFilter::clone() const
IFilter::PreflightResult MergeColoniesFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler,
const std::atomic_bool& shouldCancel) const
{
auto pFeaturePhasesArrayPathValue = filterArgs.value<DataPath>(k_FeaturePhasesArrayPath_Key);
auto pAvgQuatsArrayPathValue = filterArgs.value<DataPath>(k_AvgQuatsArrayPath_Key);
auto pFeatureIdsArrayPathValue = filterArgs.value<DataPath>(k_FeatureIdsArrayPath_Key);
auto pCellPhasesArrayPathValue = filterArgs.value<DataPath>(k_CellPhasesArrayPath_Key);
auto pCrystalStructuresArrayPathValue = filterArgs.value<DataPath>(k_CrystalStructuresArrayPath_Key);
auto pCellParentIdsArrayNameValue = filterArgs.value<DataPath>(k_CellParentIdsArrayName_Key);
auto pNewCellFeatureAttributeMatrixNameValue = filterArgs.value<DataPath>(k_NewCellFeatureAttributeMatrixName_Key);
auto pFeatureParentIdsArrayNameValue = filterArgs.value<DataPath>(k_FeatureParentIdsArrayName_Key);
auto pActiveArrayNameValue = filterArgs.value<DataPath>(k_ActiveArrayName_Key);
auto pFeaturePhasesPathValue = filterArgs.value<DataPath>(k_FeaturePhasesArrayPath_Key);
auto pAvgQuatsPathValue = filterArgs.value<DataPath>(k_AvgQuatsArrayPath_Key);
auto pFeatureIdsPathValue = filterArgs.value<DataPath>(k_FeatureIdsArrayPath_Key);
auto pCellPhasesPathValue = filterArgs.value<DataPath>(k_CellPhasesArrayPath_Key);
auto pCrystalStructuresPathValue = filterArgs.value<DataPath>(k_CrystalStructuresArrayPath_Key);
auto pCellParentIdsNameValue = filterArgs.value<std::string>(k_CellParentIdsArrayName_Key);
auto pCellFeatureAMPathValue = filterArgs.value<DataPath>(k_NewCellFeatureAttributeMatrixName_Key);
auto pFeatureParentIdsNameValue = filterArgs.value<std::string>(k_FeatureParentIdsArrayName_Key);
auto pActiveNameValue = filterArgs.value<std::string>(k_ActiveArrayName_Key);

PreflightResult preflightResult;
complex::Result<OutputActions> resultOutputActions;
std::vector<PreflightValue> preflightUpdatedValues;

// Create the CreateArray action and add it to the resultOutputActions object
{
auto action = std::make_unique<CreateAttributeMatrixAction>(pCellFeatureAMPathValue, std::vector<usize>{0});
resultOutputActions.value().appendAction(std::move(action));
}

// Create the CreateArray action and add it to the resultOutputActions object
{
auto action = std::make_unique<CreateArrayAction>(DataType::boolean, std::vector<usize>{0}, std::vector<usize>{1}, pCellFeatureAMPathValue.createChildPath(pActiveNameValue));
resultOutputActions.value().appendAction(std::move(action));
}

// Create the CreateArray action and add it to the resultOutputActions object
{
std::vector<usize> tupDims = dataStructure.getDataAs<IArray>(pFeaturePhasesPathValue)->getTupleShape();
DataPath featureParentIdsPath = pFeaturePhasesPathValue.getParent().createChildPath(pFeatureParentIdsNameValue);
auto action = std::make_unique<CreateArrayAction>(DataType::int32, tupDims, std::vector<usize>{1}, featureParentIdsPath);
resultOutputActions.value().appendAction(std::move(action));
}

// Create the CreateArray action and add it to the resultOutputActions object
{
std::vector<usize> tupDims = dataStructure.getDataAs<IArray>(pFeatureIdsPathValue)->getTupleShape();
DataPath cellParentIdsPath = pFeatureIdsPathValue.getParent().createChildPath(pCellParentIdsNameValue);
auto action = std::make_unique<CreateArrayAction>(DataType::int32, tupDims, std::vector<usize>{1}, cellParentIdsPath);
resultOutputActions.value().appendAction(std::move(action));
}

// Return both the resultOutputActions and the preflightUpdatedValues via std::move()
return {std::move(resultOutputActions), std::move(preflightUpdatedValues)};
}
Expand All @@ -123,17 +160,24 @@ Result<> MergeColoniesFilter::executeImpl(DataStructure& dataStructure, const Ar
{
MergeColoniesInputValues inputValues;

auto seed = filterArgs.value<uint64>(k_SeedValue_Key);
if(!filterArgs.value<bool>(k_UseSeed_Key))
{
seed = static_cast<std::mt19937_64::result_type>(std::chrono::steady_clock::now().time_since_epoch().count());
}

inputValues.SeedValue = seed;
inputValues.AxisTolerance = filterArgs.value<float32>(k_AxisTolerance_Key);
inputValues.AngleTolerance = filterArgs.value<float32>(k_AngleTolerance_Key);
inputValues.FeaturePhasesPath = filterArgs.value<DataPath>(k_FeaturePhasesArrayPath_Key);
inputValues.AvgQuatsPath = filterArgs.value<DataPath>(k_AvgQuatsArrayPath_Key);
inputValues.FeatureIdsPath = filterArgs.value<DataPath>(k_FeatureIdsArrayPath_Key);
inputValues.CellPhasesPath = filterArgs.value<DataPath>(k_CellPhasesArrayPath_Key);
inputValues.CrystalStructuresPath = filterArgs.value<DataPath>(k_CrystalStructuresArrayPath_Key);
inputValues.CellParentIdsPath = filterArgs.value<DataPath>(k_CellParentIdsArrayName_Key);
inputValues.CellParentIdsPath = inputValues.FeatureIdsPath.getParent().createChildPath(filterArgs.value<std::string>(k_CellParentIdsArrayName_Key));
inputValues.CellFeatureAMPath = filterArgs.value<DataPath>(k_NewCellFeatureAttributeMatrixName_Key);
inputValues.FeatureParentIdsPath = filterArgs.value<DataPath>(k_FeatureParentIdsArrayName_Key);
inputValues.ActivePath = filterArgs.value<DataPath>(k_ActiveArrayName_Key);
inputValues.FeatureParentIdsPath = inputValues.FeaturePhasesPath.getParent().createChildPath(filterArgs.value<std::string>(k_FeatureParentIdsArrayName_Key));
inputValues.ActivePath = inputValues.CellFeatureAMPath.createChildPath(filterArgs.value<std::string>(k_ActiveArrayName_Key));

GroupFeaturesInputValues gpInputValues;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class ORIENTATIONANALYSIS_EXPORT MergeColoniesFilter : public IFilter
static inline constexpr StringLiteral k_NewCellFeatureAttributeMatrixName_Key = "new_cell_feature_attribute_matrix_name";
static inline constexpr StringLiteral k_FeatureParentIdsArrayName_Key = "feature_parent_ids_array_name";
static inline constexpr StringLiteral k_ActiveArrayName_Key = "active_array_name";
static inline constexpr StringLiteral k_UseSeed_Key = "use_seed";
static inline constexpr StringLiteral k_SeedValue_Key = "seed_value";

/**
* @brief Returns the name of the filter.
Expand Down
15 changes: 3 additions & 12 deletions src/Plugins/OrientationAnalysis/test/MergeColoniesTest.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
#include <catch2/catch.hpp>

#include "complex/Parameters/ArrayCreationParameter.hpp"
#include "complex/Parameters/ArraySelectionParameter.hpp"
#include "complex/Parameters/BoolParameter.hpp"
#include "complex/Parameters/NumberParameter.hpp"

#include "ComplexCore/ComplexCore_test_dirs.hpp"
#include "ComplexCore/Filters/MergeColoniesFilter.hpp"
#include "OrientationAnalysis/Filters/MergeColoniesFilter.hpp"
#include "OrientationAnalysis/OrientationAnalysis_test_dirs.hpp"

using namespace complex;

TEST_CASE("ComplexCore::MergeColoniesFilter: Valid Filter Execution", "[ComplexCore][MergeColoniesFilter][.][UNIMPLEMENTED][!mayfail]")
TEST_CASE("OrientationAnalysis::MergeColoniesFilter: Valid Filter Execution", "[ComplexCore][MergeColoniesFilter]")
{
// Instantiate the filter, a DataStructure object and an Arguments Object
MergeColoniesFilter filter;
Expand All @@ -23,14 +21,12 @@ TEST_CASE("ComplexCore::MergeColoniesFilter: Valid Filter Execution", "[ComplexC
args.insertOrAssign(MergeColoniesFilter::k_ContiguousNeighborListArrayPath_Key, std::make_any<DataPath>(DataPath{}));
args.insertOrAssign(MergeColoniesFilter::k_AxisTolerance_Key, std::make_any<float32>(1.23345f));
args.insertOrAssign(MergeColoniesFilter::k_AngleTolerance_Key, std::make_any<float32>(1.23345f));
args.insertOrAssign(MergeColoniesFilter::k_IdentifyGlobAlpha_Key, std::make_any<bool>(false));
args.insertOrAssign(MergeColoniesFilter::k_FeaturePhasesArrayPath_Key, std::make_any<DataPath>(DataPath{}));
args.insertOrAssign(MergeColoniesFilter::k_AvgQuatsArrayPath_Key, std::make_any<DataPath>(DataPath{}));
args.insertOrAssign(MergeColoniesFilter::k_FeatureIdsArrayPath_Key, std::make_any<DataPath>(DataPath{}));
args.insertOrAssign(MergeColoniesFilter::k_CellPhasesArrayPath_Key, std::make_any<DataPath>(DataPath{}));
args.insertOrAssign(MergeColoniesFilter::k_CrystalStructuresArrayPath_Key, std::make_any<DataPath>(DataPath{}));
args.insertOrAssign(MergeColoniesFilter::k_CellParentIdsArrayName_Key, std::make_any<DataPath>(DataPath{}));
args.insertOrAssign(MergeColoniesFilter::k_GlobAlphaArrayName_Key, std::make_any<DataPath>(DataPath{}));
args.insertOrAssign(MergeColoniesFilter::k_NewCellFeatureAttributeMatrixName_Key, std::make_any<DataPath>(DataPath{}));
args.insertOrAssign(MergeColoniesFilter::k_FeatureParentIdsArrayName_Key, std::make_any<DataPath>(DataPath{}));
args.insertOrAssign(MergeColoniesFilter::k_ActiveArrayName_Key, std::make_any<DataPath>(DataPath{}));
Expand All @@ -43,8 +39,3 @@ TEST_CASE("ComplexCore::MergeColoniesFilter: Valid Filter Execution", "[ComplexC
auto executeResult = filter.execute(ds, args);
REQUIRE(executeResult.result.valid());
}

// TEST_CASE("ComplexCore::MergeColoniesFilter: InValid Filter Execution")
//{
//
// }

0 comments on commit ea43fe6

Please sign in to comment.