From 85b9aed1648187bf15ec7f99c0c2a02fe112b9cf Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Wed, 10 Dec 2025 10:21:13 -0500 Subject: [PATCH 1/2] FILT: Compute Direction Vectors filter has been added. No unit test has been created. --- CMakeLists.txt | 2 + docs/ComputeDirectionVectorsFilter.md | 28 ++ .../Algorithms/ComputeDirectionVectors.cpp | 253 ++++++++++++++++++ .../Algorithms/ComputeDirectionVectors.hpp | 53 ++++ .../Filters/ComputeDirectionVectorsFilter.cpp | 138 ++++++++++ .../Filters/ComputeDirectionVectorsFilter.hpp | 117 ++++++++ 6 files changed, 591 insertions(+) create mode 100644 docs/ComputeDirectionVectorsFilter.md create mode 100644 src/SimplnxReview/Filters/Algorithms/ComputeDirectionVectors.cpp create mode 100644 src/SimplnxReview/Filters/Algorithms/ComputeDirectionVectors.hpp create mode 100644 src/SimplnxReview/Filters/ComputeDirectionVectorsFilter.cpp create mode 100644 src/SimplnxReview/Filters/ComputeDirectionVectorsFilter.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ca682c2..62ae0cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,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 + ComputeDirectionVectorsFilter ComputeLocalAverageCAxisMisalignmentsFilter ComputeMicroTextureRegionsFilter ComputeSaltykovSizesFilter @@ -46,6 +47,7 @@ set(ActionList # This should be integrated with the `create_simplnx_plugin` function call # ------------------------------------------------------------------------------ set(AlgorithmList + ComputeDirectionVectors ComputeLocalAverageCAxisMisalignments ComputeMicroTextureRegions ComputeSaltykovSizes diff --git a/docs/ComputeDirectionVectorsFilter.md b/docs/ComputeDirectionVectorsFilter.md new file mode 100644 index 0000000..3fed27a --- /dev/null +++ b/docs/ComputeDirectionVectorsFilter.md @@ -0,0 +1,28 @@ +# Compute Direction Vectors + +**THIS FILTER IS UNTESTED, UNVERIFIED AND UNVALIDATED. IT IS AN EXPERIMENTAL FILTER THAT IS UNDERGOING LONG TERM DEVELOPMENT +AND TESTING. USE AT YOUR OWN RISK** + +## Group (Subgroup) + +Visualization Helpers + +## Description + +This **Filter** computes the crystallographic Z Axis in a cartesian coordinate system. + +This results from this filter can then be used in various visualization applications to visually inspect the crystallographic system. + +% Auto generated parameter table will be inserted here + +## References + +## 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/ComputeDirectionVectors.cpp b/src/SimplnxReview/Filters/Algorithms/ComputeDirectionVectors.cpp new file mode 100644 index 0000000..71bab35 --- /dev/null +++ b/src/SimplnxReview/Filters/Algorithms/ComputeDirectionVectors.cpp @@ -0,0 +1,253 @@ +#include "ComputeDirectionVectors.hpp" + +#include "EbsdLib/Core/Orientation.hpp" +#include "EbsdLib/Orientation/AxisAngle.hpp" +#include "EbsdLib/Orientation/Euler.hpp" +#include "EbsdLib/Orientation/OrientationMatrix.hpp" +#include "EbsdLib/Orientation/Quaternion.hpp" +#include "EbsdLib/Orientation/Rodrigues.hpp" + +#include + +#include "simplnx/Common/Constants.hpp" +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/Utilities/DataArrayUtilities.hpp" +#include "simplnx/Utilities/ParallelTaskAlgorithm.hpp" + +using namespace nx::core; + +namespace +{ +/** + * + * @param latticeParameters The lattice Parameters in the order, a, b, c, alpha, beta, gamma. Note that alpha, beta, gamma are all stored as degrees. + * @return + */ +template +ebsdlib::Matrix3X3 DirectStructureMatrix(const Vec3& latticeParametersLengths, const Vec3& latticeParametersAngles) +{ + /* This code is taken from EMsoftOO/mod_crystallography.f90 - computeMatrices() function */ + + T a = latticeParametersLengths[0]; + T b = latticeParametersLengths[1]; + T c = latticeParametersLengths[2]; + T alpha = latticeParametersAngles[0]; + T beta = latticeParametersAngles[1]; + T gamma = latticeParametersAngles[2]; + + // auxiliary variables for the various tensors + T pirad = Constants::k_PiOver180F; + T ca = std::cos(pirad * alpha); + T cb = std::cos(pirad * beta); + T cg = std::cos(pirad * gamma); + T sg = std::sin(pirad * gamma); + + // cell volume via the determinant of dmt + T det = (a * b * c) * (a * b * c) * (1.0f - ca * ca - cb * cb - cg * cg + 1.0f * ca * cb * cg); + T vol = std::sqrt(det); + + ebsdlib::Matrix3X3 dsm; + dsm[0] = a; + dsm[1] = b * cg; + dsm[2] = c * cb; + dsm[3] = 0.0; + dsm[4] = b * sg; + dsm[5] = -c * (cb * cg - ca) / sg; + dsm[6] = 0.0; + dsm[7] = 0.0; + dsm[8] = vol / (a * b * sg); + return dsm; +} + +template +class ComputeDirectionVectorsImpl +{ +public: + ComputeDirectionVectorsImpl(const DataArray& inputOrientationsArray, ebsdlib::orientations::Type inputRepType, const ebsdlib::Matrix3X1& cartesian, Float32Array& outputArray, + const std::atomic_bool& shouldCancel) + : m_InputOrientationsArray(inputOrientationsArray) + , m_InputRepType(inputRepType) + , m_Cartesian(cartesian) + , m_OutputArray(outputArray) + , m_ShouldCancel(shouldCancel) + { + } + ~ComputeDirectionVectorsImpl() = default; + + ComputeDirectionVectorsImpl(const ComputeDirectionVectorsImpl&) = default; + ComputeDirectionVectorsImpl(ComputeDirectionVectorsImpl&&) noexcept = default; + ComputeDirectionVectorsImpl& operator=(const ComputeDirectionVectorsImpl&) = delete; + ComputeDirectionVectorsImpl& operator=(ComputeDirectionVectorsImpl&&) noexcept = delete; + + void convert(usize start, usize end) const + { + // For each orientation matrix, convert to gmatrix, transpose, and multiply by the cartesian point. + // The result is the direction vector that will be stored in the output array. + + const auto& inputOrientationsDataStore = m_InputOrientationsArray.template getIDataStoreRefAs>(); + auto& outputDataStore = m_OutputArray.template getIDataStoreRefAs>(); + ebsdlib::OrientationMatrix om; + for(usize i = start; i < end; i++) + { + if(m_ShouldCancel) + { + return; + } + + switch(m_InputRepType) + { + case ebsdlib::orientations::Type::Euler: { + // Euler has 3 components + om = ebsdlib::Euler(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix(); + break; + } + case ebsdlib::orientations::Type::OrientationMatrix: { + // OrientationMatrix has 9 components + om = ebsdlib::OrientationMatrix(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2), + inputOrientationsDataStore.getValue(i * 3 + 3), inputOrientationsDataStore.getValue(i * 3 + 4), inputOrientationsDataStore.getValue(i * 3 + 5), + inputOrientationsDataStore.getValue(i * 3 + 6), inputOrientationsDataStore.getValue(i * 3 + 7), inputOrientationsDataStore.getValue(i * 3 + 8)); + break; + } + case ebsdlib::orientations::Type::Rodrigues: { + // Rodrigues has 4 components + om = ebsdlib::Rodrigues(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2), + inputOrientationsDataStore.getValue(i * 3 + 3)) + .toOrientationMatrix(); + break; + } + case ebsdlib::orientations::Type::Quaternion: { + // Quaternion has 4 components + om = ebsdlib::Quaternion(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2), + inputOrientationsDataStore.getValue(i * 3 + 3)) + .toOrientationMatrix(); + break; + } + case ebsdlib::orientations::Type::AxisAngle: { + // AxisAngle has 4 components + om = ebsdlib::AxisAngle(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2), + inputOrientationsDataStore.getValue(i * 3 + 3)) + .toOrientationMatrix(); + break; + } + case ebsdlib::orientations::Type::Homochoric: { + // Homochoric has 3 components + om = ebsdlib::Homochoric(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix(); + break; + } + case ebsdlib::orientations::Type::Cubochoric: { + // Cubochoric has 3 components + om = ebsdlib::Cubochoric(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix(); + break; + } + case ebsdlib::orientations::Type::Stereographic: { + // Stereographic has 3 components + om = + ebsdlib::Stereographic(inputOrientationsDataStore.getValue(i * 3), inputOrientationsDataStore.getValue(i * 3 + 1), inputOrientationsDataStore.getValue(i * 3 + 2)).toOrientationMatrix(); + break; + } + case ebsdlib::orientations::Type::Unknown: { + throw std::runtime_error("Unknown Orientation Representation Type. This should not happen, contact the developers."); + } + } + + ebsdlib::Matrix3X1 point = om.toGMatrix().transpose() * m_Cartesian; + std::copy(point.data(), point.data() + 3, outputDataStore.begin() + i * outputDataStore.getNumberOfComponents()); + + // std::cout << fmt::format("Cartesian: ({}, {}, {})", m_Cartesian[0], m_Cartesian[1], m_Cartesian[2]) << std::endl; + // std::cout << fmt::format("Point: ({}, {}, {})", point[0], point[1], point[2]) << std::endl; + } + } + + void operator()() const + { + convert(0, m_InputOrientationsArray.getNumberOfTuples()); + } + +private: + const DataArray& m_InputOrientationsArray; + Float32Array& m_OutputArray; + const ebsdlib::Matrix3X1& m_Cartesian; + ebsdlib::orientations::Type m_InputRepType; + const std::atomic_bool& m_ShouldCancel; +}; + +template || std::is_same_v>> +Result<> ExecuteComputeDirectionVectors(DataStructure& dataStructure, const DataPath& inputOrientationsArrayPath, const DataPath& outputArrayPath, ebsdlib::orientations::Type inputRepType, + const Vec3& latticeParametersLengths, const Vec3& latticeParametersAngles, const IFilter::MessageHandler& msgHandler, + const std::atomic_bool& shouldCancel) +{ + msgHandler("Computing Direction Vectors..."); + + // Convert the lattice parameters to a direct structure matrix, and calculate the cartesian point + ebsdlib::Matrix3X3 dsm = DirectStructureMatrix(latticeParametersLengths, latticeParametersAngles); + ebsdlib::Matrix3X1 latticePoint(0.0f, 0.0f, 1.0f); + auto cartesian = dsm * latticePoint; + + // Parallelize the implementation method + ParallelTaskAlgorithm taskRunner; + auto& inputOrientationsArray = dataStructure.getDataRefAs>(inputOrientationsArrayPath); + auto& outputArray = dataStructure.getDataRefAs(outputArrayPath); + taskRunner.template execute<>(ComputeDirectionVectorsImpl(inputOrientationsArray, inputRepType, cartesian, outputArray, shouldCancel)); + + return {}; +} +} // namespace + +// ----------------------------------------------------------------------------- +ComputeDirectionVectors::ComputeDirectionVectors(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, + ComputeDirectionVectorsInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +ComputeDirectionVectors::~ComputeDirectionVectors() noexcept = default; + +// ----------------------------------------------------------------------------- +Result<> ComputeDirectionVectors::operator()() +{ + Vec3 latticeParametersLengths; + Vec3 latticeParametersAngles; + switch(m_InputValues->LatticeConstantsInputType) + { + case LatticeConstantsInputType::DataArrayPath: { + auto& latticeConstantsArray = m_DataStructure.getDataRefAs(m_InputValues->LatticeConstantsArrayPath); + latticeParametersLengths[0] = latticeConstantsArray[0]; + latticeParametersLengths[1] = latticeConstantsArray[1]; + latticeParametersLengths[2] = latticeConstantsArray[2]; + latticeParametersAngles[0] = latticeConstantsArray[3]; + latticeParametersAngles[1] = latticeConstantsArray[4]; + latticeParametersAngles[2] = latticeConstantsArray[5]; + break; + } + case LatticeConstantsInputType::Manual: { + latticeParametersLengths = m_InputValues->ManualLatticeConstantsLengths; + latticeParametersAngles = m_InputValues->ManualLatticeConstantsAngles; + break; + } + } + + DataPath orientationsParentPath = m_InputValues->InputOrientationsArrayPath.getParent(); + DataPath outputDirectionVectorsPath = orientationsParentPath.createChildPath(m_InputValues->OutputDirectionVectorsArrayName); + + auto& inputOrientationsArray = m_DataStructure.getDataRefAs(m_InputValues->InputOrientationsArrayPath); + DataType inputDataType = inputOrientationsArray.getDataType(); + switch(inputDataType) + { + case DataType::float32: { + return ExecuteComputeDirectionVectors(m_DataStructure, m_InputValues->InputOrientationsArrayPath, outputDirectionVectorsPath, m_InputValues->InputRepType, latticeParametersLengths, + latticeParametersAngles, m_MessageHandler, m_ShouldCancel); + } + case DataType::float64: { + return ExecuteComputeDirectionVectors(m_DataStructure, m_InputValues->InputOrientationsArrayPath, outputDirectionVectorsPath, m_InputValues->InputRepType, latticeParametersLengths, + latticeParametersAngles, m_MessageHandler, m_ShouldCancel); + } + default: { + return MakeErrorResult( + -2300, fmt::format("Input Orientations array has incompatible data type: the data type is {} but this filter only supports float32 and float64 data types.", DataTypeToString(inputDataType))); + } + } +} diff --git a/src/SimplnxReview/Filters/Algorithms/ComputeDirectionVectors.hpp b/src/SimplnxReview/Filters/Algorithms/ComputeDirectionVectors.hpp new file mode 100644 index 0000000..58aedc8 --- /dev/null +++ b/src/SimplnxReview/Filters/Algorithms/ComputeDirectionVectors.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include "SimplnxReview/SimplnxReview_export.hpp" + +#include "EbsdLib/Orientation/OrientationFwd.hpp" + +#include "simplnx/Common/Array.hpp" +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Parameters/ChoicesParameter.hpp" + +namespace nx::core +{ +enum LatticeConstantsInputType : uint8 +{ + DataArrayPath = 0, + Manual = 1 +}; + +struct SIMPLNXREVIEW_EXPORT ComputeDirectionVectorsInputValues +{ + ebsdlib::orientations::Type InputRepType; + DataPath InputOrientationsArrayPath; + LatticeConstantsInputType LatticeConstantsInputType; + DataPath LatticeConstantsArrayPath; + FloatVec3 ManualLatticeConstantsLengths; + FloatVec3 ManualLatticeConstantsAngles; + std::string OutputDirectionVectorsArrayName; +}; + +/** + * @class + */ +class SIMPLNXREVIEW_EXPORT ComputeDirectionVectors +{ +public: + ComputeDirectionVectors(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeDirectionVectorsInputValues* inputValues); + ~ComputeDirectionVectors() noexcept; + + ComputeDirectionVectors(const ComputeDirectionVectors&) = delete; + ComputeDirectionVectors(ComputeDirectionVectors&&) noexcept = delete; + ComputeDirectionVectors& operator=(const ComputeDirectionVectors&) = delete; + ComputeDirectionVectors& operator=(ComputeDirectionVectors&&) noexcept = delete; + + Result<> operator()(); + +private: + DataStructure& m_DataStructure; + const ComputeDirectionVectorsInputValues* m_InputValues = nullptr; + const std::atomic_bool& m_ShouldCancel; + const IFilter::MessageHandler& m_MessageHandler; +}; +} // namespace nx::core diff --git a/src/SimplnxReview/Filters/ComputeDirectionVectorsFilter.cpp b/src/SimplnxReview/Filters/ComputeDirectionVectorsFilter.cpp new file mode 100644 index 0000000..8f4bb8a --- /dev/null +++ b/src/SimplnxReview/Filters/ComputeDirectionVectorsFilter.cpp @@ -0,0 +1,138 @@ +#include "ComputeDirectionVectorsFilter.hpp" +#include "Algorithms/ComputeDirectionVectors.hpp" + +#include "EbsdLib/Core/EbsdDataArray.hpp" +#include "EbsdLib/OrientationMath/OrientationConverter.hpp" + +#include "simplnx/DataStructure/IDataArray.hpp" +#include "simplnx/Filter/Actions/CreateArrayAction.hpp" +#include "simplnx/Parameters/ArraySelectionParameter.hpp" +#include "simplnx/Parameters/DataObjectNameParameter.hpp" +#include "simplnx/Parameters/VectorParameter.hpp" + +namespace nx::core +{ +namespace +{ +// constexpr int32 k_MissingInputArray = -567; +// constexpr int32 k_ComponentCountMismatchError = -90003; +// constexpr int32 k_InvalidNumTuples = -90004; +} // namespace + +//------------------------------------------------------------------------------ +std::string ComputeDirectionVectorsFilter::name() const +{ + return FilterTraits::name; +} + +//------------------------------------------------------------------------------ +std::string ComputeDirectionVectorsFilter::className() const +{ + return FilterTraits::className; +} + +//------------------------------------------------------------------------------ +Uuid ComputeDirectionVectorsFilter::uuid() const +{ + return FilterTraits::uuid; +} + +//------------------------------------------------------------------------------ +std::string ComputeDirectionVectorsFilter::humanName() const +{ + return "Compute Direction Vectors"; +} + +//------------------------------------------------------------------------------ +std::vector ComputeDirectionVectorsFilter::defaultTags() const +{ + return {className(), "Statistics", "SimplnxCore", "Find"}; +} + +//------------------------------------------------------------------------------ +Parameters ComputeDirectionVectorsFilter::parameters() const +{ + Parameters params; + + using OrientationConverterType = ebsdlib::OrientationConverter, float32>; + + params.insertSeparator(Parameters::Separator{"Input Parameter(s)"}); + params.insert(std::make_unique(k_InputType_Key, "Input Orientation Type", "Specifies the incoming orientation representation enumeration index", 0, + OrientationConverterType::GetOrientationTypeStrings())); + params.insert(std::make_unique(k_InputOrientationArrayPath_Key, "Input Orientations", "The complete path to the incoming orientation representation data array", DataPath{}, + ArraySelectionParameter::AllowedTypes{DataType::float32, DataType::float64}, ArraySelectionParameter::AllowedComponentShapes{{3}, {4}, {9}})); + params.insertLinkableParameter(std::make_unique(k_LatticeConstantsInputType_Key, "Lattice Constants Input Type", + "Specifies the method that the lattice constants will be input into this filter.", 0, + ChoicesParameter::Choices{"Existing Array", "Manual Entry"})); + params.insert(std::make_unique(k_LatticeConstantsArrayPath_Key, "Lattice Constants", + "The complete path to the lattice constants data array that will be imported and used by this filter.", DataPath{}, + ArraySelectionParameter::AllowedTypes{DataType::float32}, ArraySelectionParameter::AllowedComponentShapes{{6}})); + params.insert(std::make_unique(k_LatticeConstantsLength_Key, "Lattice Constants Lengths (A, B, C)", "The manual lattice constants that will be used by this filter.", + VectorFloat32Parameter::ValueType{0.0f, 0.0f, 0.0f}, std::vector{"a", "b", "c"})); + params.insert(std::make_unique(k_LatticeConstantsAngles_Key, "Lattice Constants Angles (Alpha, Beta, Gamma)", + "The manual lattice constants that will be used by this filter.", VectorFloat32Parameter::ValueType{0.0f, 0.0f, 0.0f}, + std::vector{"alpha", "beta", "gamma"})); + + params.insertSeparator(Parameters::Separator{"Output Parameter(s)"}); + params.insert(std::make_unique(k_OutputDirectionVectorsArrayName_Key, "Output Direction Vectors Array Name", + "The name of the output direction vectors array that will be created.", "Direction Vectors")); + + params.linkParameters(k_LatticeConstantsInputType_Key, k_LatticeConstantsArrayPath_Key, std::make_any(0)); + params.linkParameters(k_LatticeConstantsInputType_Key, k_LatticeConstantsLength_Key, std::make_any(1)); + params.linkParameters(k_LatticeConstantsInputType_Key, k_LatticeConstantsAngles_Key, std::make_any(1)); + + return params; +} + +//------------------------------------------------------------------------------ +IFilter::VersionType ComputeDirectionVectorsFilter::parametersVersion() const +{ + return 1; +} + +//------------------------------------------------------------------------------ +IFilter::UniquePointer ComputeDirectionVectorsFilter::clone() const +{ + return std::make_unique(); +} + +//------------------------------------------------------------------------------ +IFilter::PreflightResult ComputeDirectionVectorsFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler, + const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const +{ + auto inputRepType = static_cast(filterArgs.value(k_InputType_Key)); + auto inputOrientationsArrayPath = filterArgs.value(k_InputOrientationArrayPath_Key); + auto latticeConstantsType = static_cast(filterArgs.value(k_LatticeConstantsInputType_Key)); + auto latticeConstantsArrayPath = filterArgs.value(k_LatticeConstantsArrayPath_Key); + auto latticeConstantsLengths = filterArgs.value(k_LatticeConstantsLength_Key); + auto latticeConstantsAngles = filterArgs.value(k_LatticeConstantsAngles_Key); + auto outputDirectionVectorsArrayName = filterArgs.value(k_OutputDirectionVectorsArrayName_Key); + + DataPath orientationsParentPath = inputOrientationsArrayPath.getParent(); + DataPath outputDirectionVectorsPath = orientationsParentPath.createChildPath(outputDirectionVectorsArrayName); + auto& orientationsArray = dataStructure.getDataRefAs(inputOrientationsArrayPath); + + nx::core::Result resultOutputActions; + auto action = std::make_unique(DataType::float32, orientationsArray.getTupleShape(), std::vector{3}, outputDirectionVectorsPath); + resultOutputActions.value().appendAction(std::move(action)); + + return {std::move(resultOutputActions)}; +} + +//------------------------------------------------------------------------------ +Result<> ComputeDirectionVectorsFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, + const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const +{ + ComputeDirectionVectorsInputValues inputValues; + + inputValues.InputRepType = static_cast(filterArgs.value(k_InputType_Key)); + inputValues.InputOrientationsArrayPath = filterArgs.value(k_InputOrientationArrayPath_Key); + inputValues.LatticeConstantsInputType = static_cast(filterArgs.value(k_LatticeConstantsInputType_Key)); + inputValues.LatticeConstantsArrayPath = filterArgs.value(k_LatticeConstantsArrayPath_Key); + inputValues.ManualLatticeConstantsLengths = filterArgs.value(k_LatticeConstantsLength_Key); + inputValues.ManualLatticeConstantsAngles = filterArgs.value(k_LatticeConstantsAngles_Key); + inputValues.OutputDirectionVectorsArrayName = filterArgs.value(k_OutputDirectionVectorsArrayName_Key); + + return ComputeDirectionVectors(dataStructure, messageHandler, shouldCancel, &inputValues)(); +} +} // namespace nx::core diff --git a/src/SimplnxReview/Filters/ComputeDirectionVectorsFilter.hpp b/src/SimplnxReview/Filters/ComputeDirectionVectorsFilter.hpp new file mode 100644 index 0000000..aa8c3ff --- /dev/null +++ b/src/SimplnxReview/Filters/ComputeDirectionVectorsFilter.hpp @@ -0,0 +1,117 @@ +#pragma once + +#include "SimplnxReview/SimplnxReview_export.hpp" + +#include "simplnx/Common/StringLiteral.hpp" +#include "simplnx/Filter/FilterTraits.hpp" +#include "simplnx/Filter/IFilter.hpp" + +namespace nx::core +{ +/** + * @class ComputeDirectionVectorsFilter + * @brief + */ +class SIMPLNXREVIEW_EXPORT ComputeDirectionVectorsFilter : public IFilter +{ +public: + ComputeDirectionVectorsFilter() = default; + ~ComputeDirectionVectorsFilter() noexcept override = default; + + ComputeDirectionVectorsFilter(const ComputeDirectionVectorsFilter&) = delete; + ComputeDirectionVectorsFilter(ComputeDirectionVectorsFilter&&) noexcept = delete; + + ComputeDirectionVectorsFilter& operator=(const ComputeDirectionVectorsFilter&) = delete; + ComputeDirectionVectorsFilter& operator=(ComputeDirectionVectorsFilter&&) noexcept = delete; + + // Parameter Keys + static inline constexpr StringLiteral k_InputType_Key = "input_representation_index"; + static inline constexpr StringLiteral k_InputOrientationArrayPath_Key = "input_orientation_array_path"; + static inline constexpr StringLiteral k_LatticeConstantsInputType_Key = "lattice_constants_input_type_index"; + static inline constexpr StringLiteral k_LatticeConstantsArrayPath_Key = "lattice_constants_array_path"; + static inline constexpr StringLiteral k_LatticeConstantsLength_Key = "lattice_constants_length"; + static inline constexpr StringLiteral k_LatticeConstantsAngles_Key = "lattice_constants_angles"; + static inline constexpr StringLiteral k_OutputDirectionVectorsArrayName_Key = "output_direction_vectors_array_name"; + + /** + * @brief Returns the name of the filter. + * @return std::string + */ + std::string name() const override; + + /** + * @brief Returns the C++ classname of this filter. + * @return std::string + */ + std::string className() const override; + + /** + * @brief Returns the filter's UUID. + * @return Uuid + */ + Uuid uuid() const override; + + /** + * @brief Returns the filter name name presented to the user. + * @return std::string + */ + std::string humanName() const override; + + /** + * @brief Returns the default tags for this filter. + * @return + */ + std::vector defaultTags() const override; + + /** + * @brief Returns the parameters required to run the filter. + * @return Parameters + */ + Parameters parameters() const override; + + /** + * @brief Returns parameters version integer. + * The Initial version should always be 1. + * Should be incremented everytime the parameters change. + * @return VersionType + */ + VersionType parametersVersion() const override; + + /** + * @brief Creates a copy of the filter. + * @return IFilter::UniquePointer + */ + UniquePointer clone() const override; + +protected: + /** + * @brief Takes in a DataStructure and checks that the filter can be run on it with the given arguments. + * Returns any warnings/errors. Also returns the changes that would be applied to the DataStructure. + * Some parts of the actions may not be completely filled out if all the required information is not available at preflight time. + * @param dataStructure The input DataStructure instance + * @param filterArgs These are the input values for each parameter that is required for the filter + * @param messageHandler The MessageHandler object + * @param shouldCancel The atomic boolean that holds if the filter should be canceled + * @param executionContext The ExecutionContext that can be used to determine the correct absolute path from a relative path + * @return Returns a Result object with error or warning values if any of those occurred during execution of this function + */ + PreflightResult preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, + const ExecutionContext& executionContext) const override; + + /** + * @brief Applies the filter's algorithm to the DataStructure with the given arguments. Returns any warnings/errors. + * On failure, there is no guarantee that the DataStructure is in a correct state. + * @param dataStructure The input DataStructure instance + * @param filterArgs These are the input values for each parameter that is required for the filter + * @param pipelineNode The node in the pipeline that is being executed + * @param messageHandler The MessageHandler object + * @param shouldCancel Atomic boolean value that can be checked to cancel the filter + * @param executionContext The ExecutionContext that can be used to determine the correct absolute path from a relative path + * @return Returns a Result object with error or warning values if any of those occurred during execution of this function + */ + Result<> executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, + const ExecutionContext& executionContext) const override; +}; +} // namespace nx::core + +SIMPLNX_DEF_FILTER_TRAITS(nx::core, ComputeDirectionVectorsFilter, "1e2386db-c1a3-4e6a-b30b-34837d0a8555"); From 3d5c589afc4428bb64e3fe50de9fe5d47a872573 Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Wed, 13 May 2026 13:42:42 -0400 Subject: [PATCH 2/2] BUG: Hard code the Lattice Parameters to look at the first phase. The filter needs to be updated to also require a 'Phases' array in order for this to work properly --- .../Filters/Algorithms/ComputeDirectionVectors.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/SimplnxReview/Filters/Algorithms/ComputeDirectionVectors.cpp b/src/SimplnxReview/Filters/Algorithms/ComputeDirectionVectors.cpp index 71bab35..0dfc6b6 100644 --- a/src/SimplnxReview/Filters/Algorithms/ComputeDirectionVectors.cpp +++ b/src/SimplnxReview/Filters/Algorithms/ComputeDirectionVectors.cpp @@ -185,6 +185,7 @@ Result<> ExecuteComputeDirectionVectors(DataStructure& dataStructure, const Data // Parallelize the implementation method ParallelTaskAlgorithm taskRunner; + taskRunner.setParallelizationEnabled(false); auto& inputOrientationsArray = dataStructure.getDataRefAs>(inputOrientationsArrayPath); auto& outputArray = dataStructure.getDataRefAs(outputArrayPath); taskRunner.template execute<>(ComputeDirectionVectorsImpl(inputOrientationsArray, inputRepType, cartesian, outputArray, shouldCancel)); @@ -214,13 +215,14 @@ Result<> ComputeDirectionVectors::operator()() switch(m_InputValues->LatticeConstantsInputType) { case LatticeConstantsInputType::DataArrayPath: { + size_t phaseId = 1; auto& latticeConstantsArray = m_DataStructure.getDataRefAs(m_InputValues->LatticeConstantsArrayPath); - latticeParametersLengths[0] = latticeConstantsArray[0]; - latticeParametersLengths[1] = latticeConstantsArray[1]; - latticeParametersLengths[2] = latticeConstantsArray[2]; - latticeParametersAngles[0] = latticeConstantsArray[3]; - latticeParametersAngles[1] = latticeConstantsArray[4]; - latticeParametersAngles[2] = latticeConstantsArray[5]; + latticeParametersLengths[0] = latticeConstantsArray[phaseId * 6 + 0]; + latticeParametersLengths[1] = latticeConstantsArray[phaseId * 6 + 1]; + latticeParametersLengths[2] = latticeConstantsArray[phaseId * 6 + 2]; + latticeParametersAngles[0] = latticeConstantsArray[phaseId * 6 + 3]; + latticeParametersAngles[1] = latticeConstantsArray[phaseId * 6 + 4]; + latticeParametersAngles[2] = latticeConstantsArray[phaseId * 6 + 5]; break; } case LatticeConstantsInputType::Manual: {