From 3b176e53b6d11d2d94736c711dfa7c5b727a25c0 Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Fri, 30 Aug 2024 08:54:25 -0400 Subject: [PATCH] ENH: Add Initialize Data Array functionality to Create Data Array Signed-off-by: Michael Jackson ENH: --- src/Plugins/SimplnxCore/CMakeLists.txt | 1 + .../Filters/Algorithms/InitializeData.cpp | 336 ++++++++++++++ .../Filters/Algorithms/InitializeData.hpp | 119 +++++ .../Filters/CreateDataArrayFilter.cpp | 294 +++++++++++- .../Filters/CreateDataArrayFilter.hpp | 11 + .../Filters/InitializeDataFilter.cpp | 432 ++---------------- 6 files changed, 772 insertions(+), 421 deletions(-) create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.hpp diff --git a/src/Plugins/SimplnxCore/CMakeLists.txt b/src/Plugins/SimplnxCore/CMakeLists.txt index 9f644cc27d..d327c9280c 100644 --- a/src/Plugins/SimplnxCore/CMakeLists.txt +++ b/src/Plugins/SimplnxCore/CMakeLists.txt @@ -186,6 +186,7 @@ set(AlgorithmList ComputeTriangleGeomSizes FlyingEdges3D CreateColorMap + InitializeData LabelTriangleGeometry LaplacianSmoothing NearestPointFuseRegularGrids diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.cpp new file mode 100644 index 0000000000..c8befaa456 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.cpp @@ -0,0 +1,336 @@ + + +#include "InitializeData.hpp" + +#include "simplnx/Utilities/DataArrayUtilities.hpp" +#include "simplnx/Utilities/FilterUtilities.hpp" +#include "simplnx/Common/TypeTraits.hpp" +#include "simplnx/DataStructure/IDataArray.hpp" +#include "simplnx/DataStructure/AbstractDataStore.hpp" + +#include +#include + +using namespace nx::core; + +namespace +{ + +// At the current time this code could be simplified with a bool in the incremental template, HOWEVER, +// it was done this way to allow for expansion of operations down the line multiplication, division, etc. +template +struct IncrementalOptions +{ + static constexpr bool UsingAddition = UseAddition; + static constexpr bool UsingSubtraction = UseSubtraction; +}; + +using AdditionT = IncrementalOptions; +using SubtractionT = IncrementalOptions; + +template +void ValueFill(AbstractDataStore& dataStore, const std::vector& stringValues) +{ + usize numComp = dataStore.getNumberOfComponents(); // We checked that the values string is greater than max comps size so proceed check free + + if(numComp > 1) + { + std::vector values; + + for(const auto& str : stringValues) + { + values.emplace_back(ConvertTo::convert(str).value()); + } + + usize numTup = dataStore.getNumberOfTuples(); + + for(usize tup = 0; tup < numTup; tup++) + { + for(usize comp = 0; comp < numComp; comp++) + { + dataStore[tup * numComp + comp] = values[comp]; + } + } + } + else + { + Result result = ConvertTo::convert(stringValues[0]); + T value = result.value(); + dataStore.fill(value); + } +} + +template +void IncrementalFill(AbstractDataStore& dataStore, const std::vector& startValues, const std::vector& stepValues) +{ + usize numComp = dataStore.getNumberOfComponents(); // We checked that the values string is greater than max comps size so proceed check free + + std::vector values(numComp); + std::vector steps(numComp); + + for(usize comp = 0; comp < numComp; comp++) + { + Result result = ConvertTo::convert(startValues[comp]); + values[comp] = result.value(); + if constexpr(!std::is_same_v) + { + result = ConvertTo::convert(stepValues[comp]); + steps[comp] = result.value(); + } + } + + usize numTup = dataStore.getNumberOfTuples(); + + if constexpr(std::is_same_v) + { + for(usize comp = 0; comp < numComp; comp++) + { + dataStore[comp] = values[comp]; + + if constexpr(IncrementalOptions::UsingAddition) + { + values[comp] = ConvertTo::convert(stepValues[comp]).value() != 0 ? true : values[comp]; + } + if constexpr(IncrementalOptions::UsingSubtraction) + { + values[comp] = ConvertTo::convert(stepValues[comp]).value() != 0 ? false : values[comp]; + } + } + + for(usize tup = 1; tup < numTup; tup++) + { + for(usize comp = 0; comp < numComp; comp++) + { + dataStore[tup * numComp + comp] = values[comp]; + } + } + } + + if constexpr(!std::is_same_v) + { + for(usize tup = 0; tup < numTup; tup++) + { + for(usize comp = 0; comp < numComp; comp++) + { + dataStore[tup * numComp + comp] = values[comp]; + + if constexpr(IncrementalOptions::UsingAddition) + { + values[comp] += steps[comp]; + } + if constexpr(IncrementalOptions::UsingSubtraction) + { + values[comp] -= steps[comp]; + } + } + } + } +} + +template +void RandomFill(std::vector& dist, AbstractDataStore& dataStore, const uint64 seed, const bool standardizeSeed) +{ + usize numComp = dataStore.getNumberOfComponents(); // We checked that the values string is greater than max comps size so proceed check free + + std::vector generators(numComp, std::mt19937_64{}); + + for(usize comp = 0; comp < numComp; comp++) + { + generators[comp].seed((standardizeSeed ? seed : seed + comp)); // If standardizing seed all generators use the same else, use modified seeds + } + + usize numTup = dataStore.getNumberOfTuples(); + + for(usize tup = 0; tup < numTup; tup++) + { + for(usize comp = 0; comp < numComp; comp++) + { + if constexpr(std::is_floating_point_v) + { + if constexpr(Ranged) + { + dataStore[tup * numComp + comp] = static_cast(dist[comp](generators[comp])); + } + if constexpr(!Ranged) + { + if constexpr(std::is_signed_v) + { + dataStore[tup * numComp + comp] = static_cast(dist[comp](generators[comp]) * (std::numeric_limits::max() - 1) * (((rand() & 1) == 0) ? 1 : -1)); + } + if constexpr(!std::is_signed_v) + { + dataStore[tup * numComp + comp] = static_cast(dist[comp](generators[comp]) * std::numeric_limits::max()); + } + } + } + if constexpr(!std::is_floating_point_v) + { + dataStore[tup * numComp + comp] = static_cast(dist[comp](generators[comp])); + } + } + } +} + +template +void FillIncForwarder(const StepType& stepType, ArgsT&&... args) +{ + switch(stepType) + { + case StepType::Addition: { + ::IncrementalFill(std::forward(args)...); + return; + } + case StepType::Subtraction: { + ::IncrementalFill(std::forward(args)...); + return; + } + } +} + +template +void FillRandomForwarder(const std::vector& range, usize numComp, ArgsT&&... args) +{ + if constexpr(std::is_same_v) + { + std::vector> dists; + for(usize comp = 0; comp < numComp * 2; comp += 2) + { + dists.emplace_back((range.at(comp) ? 1 : 0), (range.at(comp + 1) ? 1 : 0)); + } + ::RandomFill>(dists, std::forward(args)...); + return; + } + if constexpr(!std::is_floating_point_v) + { + std::vector> dists; + for(usize comp = 0; comp < numComp * 2; comp += 2) + { + dists.emplace_back(range.at(comp), range.at(comp + 1)); + } + ::RandomFill>(dists, std::forward(args)...); + } + if constexpr(std::is_floating_point_v) + { + if constexpr(Ranged) + { + + std::vector> dists; + for(usize comp = 0; comp < numComp * 2; comp += 2) + { + dists.emplace_back(range.at(comp), range.at(comp + 1)); + } + ::RandomFill>(dists, std::forward(args)...); + } + if constexpr(!Ranged) + { + std::vector> dists; + for(usize comp = 0; comp < numComp * 2; comp += 2) + { + dists.emplace_back(0, 1); + } + ::RandomFill>(dists, std::forward(args)...); + } + } +} + +std::vector standardizeMultiComponent(const usize numComps, const std::vector& componentValues) +{ + if(componentValues.size() == numComps) + { + return {componentValues}; + } + else + { + std::vector standardized(numComps); + for(usize comp = 0; comp < numComps; comp++) + { + standardized[comp] = componentValues[0]; + } + return standardized; + } +} + +struct FillArrayFunctor +{ + template + void operator()(IDataArray& iDataArray, const InitializeDataInputValues& inputValues) + { + auto& dataStore = iDataArray.template getIDataStoreRefAs>(); + usize numComp = dataStore.getNumberOfComponents(); // We checked that the values string is greater than max comps size so proceed check free + + switch(inputValues.initType) + { + case InitializeType::FillValue: { + return ::ValueFill(dataStore, standardizeMultiComponent(numComp, inputValues.stringValues)); + } + case InitializeType::Incremental: { + return ::FillIncForwarder(inputValues.stepType, dataStore, standardizeMultiComponent(numComp, inputValues.startValues), standardizeMultiComponent(numComp, inputValues.stepValues)); + } + case InitializeType::Random: { + std::vector range; + if constexpr(!std::is_same_v) + { + for(usize comp = 0; comp < numComp; comp++) + { + range.push_back(std::numeric_limits::min()); + range.push_back(std::numeric_limits::max()); + } + } + if constexpr(std::is_same_v) + { + for(usize comp = 0; comp < numComp; comp++) + { + range.push_back(false); + range.push_back(true); + } + } + return ::FillRandomForwarder(range, numComp, dataStore, inputValues.seed, inputValues.standardizeSeed); + } + case InitializeType::RangedRandom: { + auto randBegin = standardizeMultiComponent(numComp, inputValues.randBegin); + auto randEnd = standardizeMultiComponent(numComp, inputValues.randEnd); + + std::vector range; + for(usize comp = 0; comp < numComp; comp++) + { + Result result = ConvertTo::convert(randBegin[comp]); + range.push_back(result.value()); + result = ConvertTo::convert(randEnd[comp]); + range.push_back(result.value()); + } + return ::FillRandomForwarder(range, numComp, dataStore, inputValues.seed, inputValues.standardizeSeed); + } + } + } +}; + +} // namespace + +// ----------------------------------------------------------------------------- +InitializeData::InitializeData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, InitializeDataInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) +{ +} + +// ----------------------------------------------------------------------------- +InitializeData::~InitializeData() noexcept = default; + +// ----------------------------------------------------------------------------- +const std::atomic_bool& InitializeData::getCancel() +{ + return m_ShouldCancel; +} + +// ----------------------------------------------------------------------------- +Result<> InitializeData::operator()() +{ + + auto& iDataArray = m_DataStructure.getDataRefAs(m_InputValues->InputArrayPath); + + ExecuteDataFunction(::FillArrayFunctor{}, iDataArray.getDataType(), iDataArray, *m_InputValues); + + return {}; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.hpp new file mode 100644 index 0000000000..3b2a620d23 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.hpp @@ -0,0 +1,119 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include "simplnx/Filter/IFilter.hpp" +#include "simplnx/Utilities/StringUtilities.hpp" +#include "simplnx/Utilities/DataArrayUtilities.hpp" + + +namespace nx::core +{ + +constexpr char k_DelimiterChar = ';'; + +enum InitializeType : uint64 +{ + FillValue, + Incremental, + Random, + RangedRandom +}; + +enum StepType : uint64 +{ + Addition, + Subtraction +}; + +struct SIMPLNXCORE_EXPORT InitializeDataInputValues +{ + DataPath InputArrayPath; + InitializeType initType; + StepType stepType; + std::vector stringValues; + std::vector startValues; + std::vector stepValues; + uint64 seed; + std::vector randBegin; + std::vector randEnd; + bool standardizeSeed; +}; + + +struct SIMPLNXCORE_EXPORT ValidateMultiInputFunctor +{ + // The single comp size validation defaults to off as size 0 is checked earlier in the function + template + IFilter::PreflightResult operator()(const usize expectedComp, const std::string& unfilteredStr, const usize singleCompSize = 0) + { + std::vector splitVals = StringUtilities::split(StringUtilities::trimmed(unfilteredStr), k_DelimiterChar); + + if(splitVals.empty()) + { + return IFilter::MakePreflightErrorResult(-11610, fmt::format("A required parameter is unable to be processed with '{}' delimiter. Input: {}", k_DelimiterChar, unfilteredStr)); + } + + for(usize comp = 0; comp < splitVals.size(); comp++) + { + if(splitVals[comp].empty()) + { + return IFilter::MakePreflightErrorResult(-11611, fmt::format("Empty value found after '{}' components were converted. Check for duplicate '{}' next to one another.", comp, k_DelimiterChar)); + } + + Result result = ConvertTo::convert(splitVals[comp]); + + if(result.invalid()) + { + return IFilter::MakePreflightErrorResult(-11612, fmt::format("Unable to process '{}' into a {} value.", splitVals[comp], DataTypeToString(GetDataType()))); + } + } + + if(splitVals.size() == expectedComp) + { + return {}; // Valid + } + + if(splitVals.size() == singleCompSize) + { + return {}; // Valid + } + + if(splitVals.size() == expectedComp + 1) + { + if(unfilteredStr.back() == k_DelimiterChar) + { + return IFilter::MakePreflightErrorResult(-11613, fmt::format("Remove the extra delimiter '{}' at the end of your value sequence: {}.", k_DelimiterChar, unfilteredStr)); + } + } + + return IFilter::MakePreflightErrorResult(-11614, + fmt::format("Using '{}' as a delimiter we are unable to break '{}' into the required {} components.", k_DelimiterChar, unfilteredStr, expectedComp)); + } +}; + + +class InitializeData +{ +public: + InitializeData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, InitializeDataInputValues* inputValues); + ~InitializeData() noexcept; + + InitializeData(const InitializeData&) = delete; + InitializeData(InitializeData&&) noexcept = delete; + InitializeData& operator=(const InitializeData&) = delete; + InitializeData& operator=(InitializeData&&) noexcept = delete; + + Result<> operator()(); + + const std::atomic_bool& getCancel(); + +private: + DataStructure& m_DataStructure; + const InitializeDataInputValues* m_InputValues = nullptr; + const std::atomic_bool& m_ShouldCancel; + const IFilter::MessageHandler& m_MessageHandler; + +}; + +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayFilter.cpp index b93e305e5c..b21912158d 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayFilter.cpp @@ -1,5 +1,7 @@ #include "CreateDataArrayFilter.hpp" +#include "SimplnxCore/Filters/Algorithms/InitializeData.hpp" + #include "simplnx/Common/TypesUtility.hpp" #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Parameters/ArrayCreationParameter.hpp" @@ -19,8 +21,6 @@ using namespace nx::core; namespace { -constexpr int32 k_EmptyParameterError = -123; - struct CreateAndInitArrayFunctor { template @@ -73,9 +73,32 @@ Parameters CreateDataArrayFilter::parameters() const params.insertSeparator(Parameters::Separator{"Input Parameter(s)"}); params.insert(std::make_unique(k_NumericType_Key, "Output Numeric Type", "Numeric Type of data to create", NumericType::int32)); - params.insert(std::make_unique(k_InitializationValue_Key, "Initialization Value", "This value will be used to fill the new array", "0")); + // params.insert(std::make_unique(k_InitializationValue_Key, "Initialization Value", "This value will be used to fill the new array", "0")); params.insert(std::make_unique(k_NumComps_Key, "Number of Components", "Number of components", 1)); + params.insertSeparator(Parameters::Separator{"Initialization Options"}); + params.insertLinkableParameter(std::make_unique(k_InitType_Key, "Initialization Type", "Method for determining the what values of the data in the array should be initialized to", + static_cast(0), + ChoicesParameter::Choices{"Fill Value", "Incremental", "Random", "Random With Range"})); // sequence dependent DO NOT REORDER + + params.insert(std::make_unique(k_InitValue_Key, "Fill Values [Seperated with ;]", + "Specify values for each component. Ex: A 3-component array would be 6;8;12 and every tuple would have these same component values", "1;1;1")); + + params.insert(std::make_unique(k_StartingFillValue_Key, "Starting Value [Seperated with ;]", "The value to start incrementing from", "0;1;2")); + params.insert(std::make_unique(k_StepOperation_Key, "Step Operation", "The type of step operation to preform", static_cast(0), + ChoicesParameter::Choices{"Addition", "Subtraction"})); + params.insert(std::make_unique(k_StepValue_Key, "Increment/Step Value [Seperated with ;]", "The number to increment/decrement the fill value by", "1;1;1")); + + params.insert(std::make_unique(k_UseSeed_Key, "Use Seed for Random Generation", "When true the Seed Value will be used to seed the generator", false)); + params.insert(std::make_unique>(k_SeedValue_Key, "Seed Value", "The seed fed into the random generator", std::mt19937::default_seed)); + params.insert(std::make_unique(k_SeedArrayName_Key, "Stored Seed Value Array Name", "Name of array holding the seed value", "InitializeDataFilter SeedValue")); + params.insert(std::make_unique(k_StandardizeSeed_Key, "Use the Same Seed for Each Component", + "When true the same seed will be used for each component's generator in a multi-component array", false)); + + params.insert( + std::make_unique(k_InitStartRange_Key, "Initialization Start Range [Seperated with ;]", "[Inclusive] The lower bound initialization range for random values", "0;0;0")); + params.insert(std::make_unique(k_InitEndRange_Key, "Initialization End Range [Seperated with ;]", "[Inclusive] The upper bound initialization range for random values", "1;1;1")); + params.insertSeparator(Parameters::Separator{"Output Data Array"}); params.insert(std::make_unique(k_DataPath_Key, "Created Array", "Array storing the data", DataPath{})); params.insert(std::make_unique(k_DataFormat_Key, "Data Format", @@ -95,6 +118,28 @@ Parameters CreateDataArrayFilter::parameters() const // Associate the Linkable Parameter(s) to the children parameters that they control params.linkParameters(k_AdvancedOptions_Key, k_TupleDims_Key, true); + // Associate the Linkable Parameter(s) to the children parameters that they control + /* Using Fill Value */ + params.linkParameters(k_InitType_Key, k_InitValue_Key, static_cast(0)); + + /* Using Incremental */ + params.linkParameters(k_InitType_Key, k_StartingFillValue_Key, static_cast(1)); + params.linkParameters(k_InitType_Key, k_StepOperation_Key, static_cast(1)); + params.linkParameters(k_InitType_Key, k_StepValue_Key, static_cast(1)); + + /* Random - Using Random */ + params.linkParameters(k_InitType_Key, k_UseSeed_Key, static_cast(2)); + params.linkParameters(k_InitType_Key, k_SeedValue_Key, static_cast(2)); + params.linkParameters(k_InitType_Key, k_SeedArrayName_Key, static_cast(2)); + params.linkParameters(k_InitType_Key, k_StandardizeSeed_Key, static_cast(2)); + + /* Random - Using Random With Range */ + params.linkParameters(k_InitType_Key, k_UseSeed_Key, static_cast(3)); + params.linkParameters(k_InitType_Key, k_SeedValue_Key, static_cast(3)); + params.linkParameters(k_InitType_Key, k_SeedArrayName_Key, static_cast(3)); + params.linkParameters(k_InitType_Key, k_StandardizeSeed_Key, static_cast(3)); + params.linkParameters(k_InitType_Key, k_InitStartRange_Key, static_cast(3)); + params.linkParameters(k_InitType_Key, k_InitEndRange_Key, static_cast(3)); return params; } @@ -112,22 +157,22 @@ IFilter::PreflightResult CreateDataArrayFilter::preflightImpl(const DataStructur auto numericType = filterArgs.value(k_NumericType_Key); auto numComponents = filterArgs.value(k_NumComps_Key); auto dataArrayPath = filterArgs.value(k_DataPath_Key); - auto initValue = filterArgs.value(k_InitializationValue_Key); auto tableData = filterArgs.value(k_TupleDims_Key); auto dataFormat = filterArgs.value(k_DataFormat_Key); + // auto initValue = filterArgs.value(k_InitializationValue_Key); nx::core::Result resultOutputActions; - if(initValue.empty()) - { - return MakePreflightErrorResult(k_EmptyParameterError, fmt::format("{}: Init Value cannot be empty.{}({})", humanName(), __FILE__, __LINE__)); - } - // Sanity check that what the user entered for an init value can be converted safely to the final numeric type - Result<> result = CheckValueConverts(initValue, numericType); - if(result.invalid()) - { - return {ConvertResultTo(std::move(result), {})}; - } +// if(initValue.empty()) +// { +// return MakePreflightErrorResult(k_EmptyParameterError, fmt::format("{}: Init Value cannot be empty.{}({})", humanName(), __FILE__, __LINE__)); +// } +// // Sanity check that what the user entered for an init value can be converted safely to the final numeric type +// Result<> result = CheckValueConverts(initValue, numericType); +// if(result.invalid()) +// { +// return {ConvertResultTo(std::move(result), {})}; +// } std::vector compDims = std::vector{numComponents}; std::vector tupleDims = {}; @@ -167,23 +212,232 @@ IFilter::PreflightResult CreateDataArrayFilter::preflightImpl(const DataStructur } } + auto arrayDataType = ConvertNumericTypeToDataType(numericType); auto action = std::make_unique(ConvertNumericTypeToDataType(numericType), tupleDims, compDims, dataArrayPath, dataFormat); resultOutputActions.value().appendAction(std::move(action)); - return {std::move(resultOutputActions)}; + auto seedArrayNameValue = filterArgs.value(k_SeedArrayName_Key); + auto initializeTypeValue = static_cast(filterArgs.value(k_InitType_Key)); + +// nx::core::Result resultOutputActions; + std::vector preflightUpdatedValues; + +// auto& iDataArray = dataStructure.getDataRefAs(filterArgs.value(k_ArrayPath_Key)); + + if(arrayDataType == DataType::boolean) + { + std::stringstream updatedValStrm; + + updatedValStrm << "We detected that you are doing an operation on a boolean array.\n"; + updatedValStrm << "The ONLY two ways to specify a 'false' boolean value are as follows:\n"; + updatedValStrm << "- boolean value string types as follows ignoring apostrophe marks: 'False', 'FALSE', 'false'\n"; + updatedValStrm << "- all well formed integers and well formed floating point definitions of 0\n\n"; + + updatedValStrm << "ANY OTHER string or number WILL BE 'true', although it is good practice to define true values as follows:\n"; + updatedValStrm << "- boolean value string types as follows ignoring apostrophe marks: 'True', 'TRUE', 'true'\n"; + updatedValStrm << "- all well formed integers and well formed floating point definitions of 1"; + + preflightUpdatedValues.push_back({"Boolean Note", updatedValStrm.str()}); + } + + if(numComponents > 1) + { + std::stringstream updatedValStrm; + + updatedValStrm << "We detected that you are doing an operation on a multi-component array.\n"; + updatedValStrm + << "If you do NOT want to use unique values for each component, you can just supply one value to the input box and we will apply that value to every component for the tuple.\nExample: 1\n\n"; + + updatedValStrm << fmt::format("If you DO want to use unique values for each component, you need to supply {} values of type {} seperated by '{}'.\n", numComponents, + DataTypeToString(arrayDataType), k_DelimiterChar); + updatedValStrm << "Example: "; + + for(usize comp = 0; comp < numComponents; comp++) + { + updatedValStrm << "1"; + + if(comp != numComponents - 1) + { + updatedValStrm << k_DelimiterChar; + } + } + + preflightUpdatedValues.push_back({"Multi-Component Note", updatedValStrm.str()}); + } + + std::stringstream operationNuancesStrm; + + switch(initializeTypeValue) + { + case InitializeType::FillValue: { + auto result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, arrayDataType, numComponents, filterArgs.value(k_InitValue_Key), 1); + if(result.outputActions.invalid()) + { + return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; + } + + operationNuancesStrm << "None to note"; + + break; + } + case InitializeType::Incremental: { + auto result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, arrayDataType, numComponents, filterArgs.value(k_StartingFillValue_Key), 1); + if(result.outputActions.invalid()) + { + return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; + } + + if(arrayDataType == DataType::boolean) + { + // custom bool checks here + std::stringstream updatedValStrm; + + updatedValStrm << "We detected that you are doing an incremental operation on a boolean array.\n"; + updatedValStrm << "For the step values please enter uint8 values, preferably a 0 or 1 only.\n"; + + switch(static_cast(filterArgs.value(k_StepOperation_Key))) + { + case Addition: { + updatedValStrm << "You have currently selected the addition operation.\nAny step value that is greater than 0 will cause all values to be 'true' after the first tuple, 'true' " + "values will remain unchanged.\n"; + updatedValStrm << "The two possibilities:\n"; + updatedValStrm << "- If your start value is 'false' and step value > 0, the array will initialize to | false | true | true | ... |\n"; + updatedValStrm << "- If your start value is 'true' and step value > 0, the array will initialize to | true | true | true | ... |"; + break; + } + case Subtraction: { + updatedValStrm << "You have currently selected the addition operation.\nAny step value that is greater than 0 will cause all values to be 'false' after the first tuple, 'false' " + "values will remain unchanged.\n"; + updatedValStrm << "The two possibilities:\n"; + updatedValStrm << "- If your start value is 'true' and step value > 0, the array will initialize to | true | false | false | ... |\n"; + updatedValStrm << "- If your start value is 'false' and step value > 0, the array will initialize to | false | false | false | ... |"; + break; + } + } + + preflightUpdatedValues.push_back({"Boolean Incremental Nuances", updatedValStrm.str()}); + + result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, DataType::uint8, numComponents, filterArgs.value(k_StepValue_Key), 1); + if(result.outputActions.invalid()) + { + return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; + } + } + else + { + result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, arrayDataType, numComponents, filterArgs.value(k_StepValue_Key), 1); + if(result.outputActions.invalid()) + { + return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; + } + } + auto values = StringUtilities::split(filterArgs.value(k_StepValue_Key), ";", false); + std::vector zeroIdx; + for(size_t i = 0; i < values.size(); i++) + { + if(values[i] == "0") + { + zeroIdx.push_back(i); + } + } + if(!zeroIdx.empty()) + { + + operationNuancesStrm << "Warning: Zero Step Value found. Component(s) " << fmt::format("[{}]", fmt::join(zeroIdx, ",")) + << " have a ZERO value for the step/increment.\n The values for those components will be unchanged from the starting value.\n"; + operationNuancesStrm << fmt::format(" Example: Suppose we have a two component array with a Step Values of '2{}0', Starting Values of '0', and an addition Step Operation\n", k_DelimiterChar); + operationNuancesStrm << " The output array would look like 0,0 | 2,0 | 4,0 | 6,0 | ..."; + } + break; + } + case InitializeType::RangedRandom: { + auto result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, arrayDataType, numComponents, filterArgs.value(k_InitStartRange_Key), 1); + if(result.outputActions.invalid()) + { + return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; + } + + result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, arrayDataType, numComponents, filterArgs.value(k_InitEndRange_Key), 1); + if(result.outputActions.invalid()) + { + return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; + } + + [[fallthrough]]; + } + case InitializeType::Random: { + auto createAction = std::make_unique(DataType::uint64, std::vector{1}, std::vector{1}, DataPath({seedArrayNameValue})); + resultOutputActions.value().appendAction(std::move(createAction)); + + if(numComponents == 1) + { + if(filterArgs.value(k_StandardizeSeed_Key)) + { + operationNuancesStrm << fmt::format("You chose to standardize the seed for each component, but the array {} is a single component so it will not alter the randomization scheme.", + dataArrayPath.getTargetName()); + } + } + else + { + if(filterArgs.value(k_StandardizeSeed_Key)) + { + operationNuancesStrm << "This generates THE SAME sequences of random numbers for each component in the array based on one seed.\n"; + operationNuancesStrm << "The resulting array will look like | 1,1,1 | 9,9,9 | ...\n"; + } + else + { + operationNuancesStrm << "This generates DIFFERENT sequences of random numbers for each component in the array based on x seeds all modified versions of an original seed.\n"; + operationNuancesStrm << "The resulting array will look like | 1,9,5 | 7,1,6 | ...\n"; + } + } + + break; + } + } + + preflightUpdatedValues.push_back({"Operation Nuances", operationNuancesStrm.str()}); + + return {std::move(resultOutputActions), std::move(preflightUpdatedValues)}; } //------------------------------------------------------------------------------ -Result<> CreateDataArrayFilter::executeImpl(DataStructure& dataStructure, const Arguments& args, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, +Result<> CreateDataArrayFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel) const { - auto path = args.value(k_DataPath_Key); - auto initValue = args.value(k_InitializationValue_Key); + auto path = filterArgs.value(k_DataPath_Key); + auto initValue = filterArgs.value(k_InitializationValue_Key); + + ExecuteNeighborFunction(CreateAndInitArrayFunctor{}, ConvertNumericTypeToDataType(filterArgs.value(k_NumericType_Key)), dataStructure.getDataAs(path), initValue); + - ExecuteNeighborFunction(CreateAndInitArrayFunctor{}, ConvertNumericTypeToDataType(args.value(k_NumericType_Key)), dataStructure.getDataAs(path), initValue); + auto initType = static_cast(filterArgs.value(k_InitType_Key)); + + auto seed = filterArgs.value(k_SeedValue_Key); + if(!filterArgs.value(k_UseSeed_Key)) + { + seed = static_cast(std::chrono::steady_clock::now().time_since_epoch().count()); + } + + if(initType == InitializeType::Random || initType == InitializeType::RangedRandom) + { + // Store Seed Value in Top Level Array + dataStructure.getDataRefAs(DataPath({filterArgs.value(k_SeedArrayName_Key)}))[0] = seed; + } - return {}; + InitializeDataInputValues inputValues; + inputValues.InputArrayPath = filterArgs.value(k_DataPath_Key); + inputValues.initType = initType; + inputValues.stepType = static_cast(filterArgs.value(k_StepOperation_Key)); + inputValues.stringValues = StringUtilities::split(StringUtilities::trimmed(filterArgs.value(k_InitValue_Key)), k_DelimiterChar); + inputValues.startValues = StringUtilities::split(StringUtilities::trimmed(filterArgs.value(k_StartingFillValue_Key)), k_DelimiterChar); + inputValues.stepValues = StringUtilities::split(StringUtilities::trimmed(filterArgs.value(k_StepValue_Key)), k_DelimiterChar); + inputValues.seed = seed; + inputValues.randBegin = StringUtilities::split(StringUtilities::trimmed(filterArgs.value(k_InitStartRange_Key)), k_DelimiterChar); + inputValues.randEnd = StringUtilities::split(StringUtilities::trimmed(filterArgs.value(k_InitEndRange_Key)), k_DelimiterChar); + inputValues.standardizeSeed = filterArgs.value(k_StandardizeSeed_Key); + + return InitializeData(dataStructure, messageHandler, shouldCancel, &inputValues)(); } namespace diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayFilter.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayFilter.hpp index e3e38e9856..6b2ac76a08 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayFilter.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayFilter.hpp @@ -28,6 +28,17 @@ class SIMPLNXCORE_EXPORT CreateDataArrayFilter : public IFilter static inline constexpr StringLiteral k_DataPath_Key = "output_array_path"; static inline constexpr StringLiteral k_InitializationValue_Key = "initialization_value_str"; static inline constexpr StringLiteral k_DataFormat_Key = "data_format"; + static inline constexpr StringLiteral k_InitType_Key = "init_type_index"; + static inline constexpr StringLiteral k_InitValue_Key = "init_value"; + static inline constexpr StringLiteral k_StartingFillValue_Key = "starting_fill_value"; + static inline constexpr StringLiteral k_StepOperation_Key = "step_operation_index"; + static inline constexpr StringLiteral k_StepValue_Key = "step_value"; + static inline constexpr StringLiteral k_UseSeed_Key = "use_seed"; + static inline constexpr StringLiteral k_SeedValue_Key = "seed_value"; + static inline constexpr StringLiteral k_SeedArrayName_Key = "seed_array_name"; + static inline constexpr StringLiteral k_InitStartRange_Key = "init_start_range"; + static inline constexpr StringLiteral k_InitEndRange_Key = "init_end_range"; + static inline constexpr StringLiteral k_StandardizeSeed_Key = "standardize_seed"; /** * @brief Reads SIMPL json and converts it simplnx Arguments. diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/InitializeDataFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/InitializeDataFilter.cpp index c7867427a1..3451cf87b6 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/InitializeDataFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/InitializeDataFilter.cpp @@ -1,6 +1,7 @@ #include "InitializeDataFilter.hpp" -#include "simplnx/Common/TypeTraits.hpp" +#include "SimplnxCore/Filters/Algorithms/InitializeData.hpp" + #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Parameters/ArraySelectionParameter.hpp" #include "simplnx/Parameters/BoolParameter.hpp" @@ -14,8 +15,7 @@ #include -#include -#include + #include #include #include @@ -24,375 +24,9 @@ using namespace nx::core; namespace { -constexpr char k_DelimiterChar = ';'; - -enum InitializeType : uint64 -{ - FillValue, - Incremental, - Random, - RangedRandom -}; - -enum StepType : uint64 -{ - Addition, - Subtraction -}; - -struct InitializeDataInputValues -{ - InitializeType initType; - StepType stepType; - std::vector stringValues; - std::vector startValues; - std::vector stepValues; - uint64 seed; - std::vector randBegin; - std::vector randEnd; - bool standardizeSeed; -}; - -// At the current time this code could be simplified with a bool in the incremental template, HOWEVER, -// it was done this way to allow for expansion of operations down the line multiplication, division, etc. -template -struct IncrementalOptions -{ - static constexpr bool UsingAddition = UseAddition; - static constexpr bool UsingSubtraction = UseSubtraction; -}; - -using AdditionT = IncrementalOptions; -using SubtractionT = IncrementalOptions; - -template -void ValueFill(AbstractDataStore& dataStore, const std::vector& stringValues) -{ - usize numComp = dataStore.getNumberOfComponents(); // We checked that the values string is greater than max comps size so proceed check free - - if(numComp > 1) - { - std::vector values; - - for(const auto& str : stringValues) - { - values.emplace_back(ConvertTo::convert(str).value()); - } - - usize numTup = dataStore.getNumberOfTuples(); - - for(usize tup = 0; tup < numTup; tup++) - { - for(usize comp = 0; comp < numComp; comp++) - { - dataStore[tup * numComp + comp] = values[comp]; - } - } - } - else - { - Result result = ConvertTo::convert(stringValues[0]); - T value = result.value(); - dataStore.fill(value); - } -} - -template -void IncrementalFill(AbstractDataStore& dataStore, const std::vector& startValues, const std::vector& stepValues) -{ - usize numComp = dataStore.getNumberOfComponents(); // We checked that the values string is greater than max comps size so proceed check free - - std::vector values(numComp); - std::vector steps(numComp); - - for(usize comp = 0; comp < numComp; comp++) - { - Result result = ConvertTo::convert(startValues[comp]); - values[comp] = result.value(); - if constexpr(!std::is_same_v) - { - result = ConvertTo::convert(stepValues[comp]); - steps[comp] = result.value(); - } - } - - usize numTup = dataStore.getNumberOfTuples(); - - if constexpr(std::is_same_v) - { - for(usize comp = 0; comp < numComp; comp++) - { - dataStore[comp] = values[comp]; - - if constexpr(IncrementalOptions::UsingAddition) - { - values[comp] = ConvertTo::convert(stepValues[comp]).value() != 0 ? true : values[comp]; - } - if constexpr(IncrementalOptions::UsingSubtraction) - { - values[comp] = ConvertTo::convert(stepValues[comp]).value() != 0 ? false : values[comp]; - } - } - - for(usize tup = 1; tup < numTup; tup++) - { - for(usize comp = 0; comp < numComp; comp++) - { - dataStore[tup * numComp + comp] = values[comp]; - } - } - } - - if constexpr(!std::is_same_v) - { - for(usize tup = 0; tup < numTup; tup++) - { - for(usize comp = 0; comp < numComp; comp++) - { - dataStore[tup * numComp + comp] = values[comp]; - - if constexpr(IncrementalOptions::UsingAddition) - { - values[comp] += steps[comp]; - } - if constexpr(IncrementalOptions::UsingSubtraction) - { - values[comp] -= steps[comp]; - } - } - } - } -} - -template -void RandomFill(std::vector& dist, AbstractDataStore& dataStore, const uint64 seed, const bool standardizeSeed) -{ - usize numComp = dataStore.getNumberOfComponents(); // We checked that the values string is greater than max comps size so proceed check free - - std::vector generators(numComp, std::mt19937_64{}); - - for(usize comp = 0; comp < numComp; comp++) - { - generators[comp].seed((standardizeSeed ? seed : seed + comp)); // If standardizing seed all generators use the same else, use modified seeds - } - - usize numTup = dataStore.getNumberOfTuples(); - - for(usize tup = 0; tup < numTup; tup++) - { - for(usize comp = 0; comp < numComp; comp++) - { - if constexpr(std::is_floating_point_v) - { - if constexpr(Ranged) - { - dataStore[tup * numComp + comp] = static_cast(dist[comp](generators[comp])); - } - if constexpr(!Ranged) - { - if constexpr(std::is_signed_v) - { - dataStore[tup * numComp + comp] = static_cast(dist[comp](generators[comp]) * (std::numeric_limits::max() - 1) * (((rand() & 1) == 0) ? 1 : -1)); - } - if constexpr(!std::is_signed_v) - { - dataStore[tup * numComp + comp] = static_cast(dist[comp](generators[comp]) * std::numeric_limits::max()); - } - } - } - if constexpr(!std::is_floating_point_v) - { - dataStore[tup * numComp + comp] = static_cast(dist[comp](generators[comp])); - } - } - } -} - -template -void FillIncForwarder(const StepType& stepType, ArgsT&&... args) -{ - switch(stepType) - { - case StepType::Addition: { - ::IncrementalFill(std::forward(args)...); - return; - } - case StepType::Subtraction: { - ::IncrementalFill(std::forward(args)...); - return; - } - } -} - -template -void FillRandomForwarder(const std::vector& range, usize numComp, ArgsT&&... args) -{ - if constexpr(std::is_same_v) - { - std::vector> dists; - for(usize comp = 0; comp < numComp * 2; comp += 2) - { - dists.emplace_back((range.at(comp) ? 1 : 0), (range.at(comp + 1) ? 1 : 0)); - } - ::RandomFill>(dists, std::forward(args)...); - return; - } - if constexpr(!std::is_floating_point_v) - { - std::vector> dists; - for(usize comp = 0; comp < numComp * 2; comp += 2) - { - dists.emplace_back(range.at(comp), range.at(comp + 1)); - } - ::RandomFill>(dists, std::forward(args)...); - } - if constexpr(std::is_floating_point_v) - { - if constexpr(Ranged) - { - std::vector> dists; - for(usize comp = 0; comp < numComp * 2; comp += 2) - { - dists.emplace_back(range.at(comp), range.at(comp + 1)); - } - ::RandomFill>(dists, std::forward(args)...); - } - if constexpr(!Ranged) - { - std::vector> dists; - for(usize comp = 0; comp < numComp * 2; comp += 2) - { - dists.emplace_back(0, 1); - } - ::RandomFill>(dists, std::forward(args)...); - } - } -} - -std::vector standardizeMultiComponent(const usize numComps, const std::vector& componentValues) -{ - if(componentValues.size() == numComps) - { - return {componentValues}; - } - else - { - std::vector standardized(numComps); - for(usize comp = 0; comp < numComps; comp++) - { - standardized[comp] = componentValues[0]; - } - return standardized; - } } -struct FillArrayFunctor -{ - template - void operator()(IDataArray& iDataArray, const InitializeDataInputValues& inputValues) - { - auto& dataStore = iDataArray.template getIDataStoreRefAs>(); - usize numComp = dataStore.getNumberOfComponents(); // We checked that the values string is greater than max comps size so proceed check free - - switch(inputValues.initType) - { - case InitializeType::FillValue: { - return ::ValueFill(dataStore, standardizeMultiComponent(numComp, inputValues.stringValues)); - } - case InitializeType::Incremental: { - return ::FillIncForwarder(inputValues.stepType, dataStore, standardizeMultiComponent(numComp, inputValues.startValues), standardizeMultiComponent(numComp, inputValues.stepValues)); - } - case InitializeType::Random: { - std::vector range; - if constexpr(!std::is_same_v) - { - for(usize comp = 0; comp < numComp; comp++) - { - range.push_back(std::numeric_limits::min()); - range.push_back(std::numeric_limits::max()); - } - } - if constexpr(std::is_same_v) - { - for(usize comp = 0; comp < numComp; comp++) - { - range.push_back(false); - range.push_back(true); - } - } - return ::FillRandomForwarder(range, numComp, dataStore, inputValues.seed, inputValues.standardizeSeed); - } - case InitializeType::RangedRandom: { - auto randBegin = standardizeMultiComponent(numComp, inputValues.randBegin); - auto randEnd = standardizeMultiComponent(numComp, inputValues.randEnd); - - std::vector range; - for(usize comp = 0; comp < numComp; comp++) - { - Result result = ConvertTo::convert(randBegin[comp]); - range.push_back(result.value()); - result = ConvertTo::convert(randEnd[comp]); - range.push_back(result.value()); - } - return ::FillRandomForwarder(range, numComp, dataStore, inputValues.seed, inputValues.standardizeSeed); - } - } - } -}; - -struct ValidateMultiInputFunctor -{ - // The single comp size validation defaults to off as size 0 is checked earlier in the function - template - IFilter::PreflightResult operator()(const usize expectedComp, const std::string& unfilteredStr, const usize singleCompSize = 0) - { - std::vector splitVals = StringUtilities::split(StringUtilities::trimmed(unfilteredStr), k_DelimiterChar); - - if(splitVals.empty()) - { - return IFilter::MakePreflightErrorResult(-11610, fmt::format("A required parameter is unable to be processed with '{}' delimiter. Input: {}", k_DelimiterChar, unfilteredStr)); - } - - for(usize comp = 0; comp < splitVals.size(); comp++) - { - if(splitVals[comp].empty()) - { - return IFilter::MakePreflightErrorResult(-11611, fmt::format("Empty value found after '{}' components were converted. Check for duplicate '{}' next to one another.", comp, k_DelimiterChar)); - } - - Result result = ConvertTo::convert(splitVals[comp]); - - if(result.invalid()) - { - return IFilter::MakePreflightErrorResult(-11612, fmt::format("Unable to process '{}' into a {} value.", splitVals[comp], DataTypeToString(GetDataType()))); - } - } - - if(splitVals.size() == expectedComp) - { - return {}; // Valid - } - - if(splitVals.size() == singleCompSize) - { - return {}; // Valid - } - - if(splitVals.size() == expectedComp + 1) - { - if(unfilteredStr.back() == k_DelimiterChar) - { - return IFilter::MakePreflightErrorResult(-11613, fmt::format("Remove the extra delimiter '{}' at the end of your value sequence: {}.", k_DelimiterChar, unfilteredStr)); - } - } - - return IFilter::MakePreflightErrorResult(-11614, - fmt::format("Using '{}' as a delimiter we are unable to break '{}' into the required {} components.", k_DelimiterChar, unfilteredStr, expectedComp)); - } -}; -} // namespace - namespace nx::core { //------------------------------------------------------------------------------ @@ -490,16 +124,16 @@ IFilter::UniquePointer InitializeDataFilter::clone() const } //------------------------------------------------------------------------------ -IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& args, const MessageHandler& messageHandler, +IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel) const { - auto seedArrayNameValue = args.value(k_SeedArrayName_Key); - auto initializeTypeValue = static_cast(args.value(k_InitType_Key)); + auto seedArrayNameValue = filterArgs.value(k_SeedArrayName_Key); + auto initializeTypeValue = static_cast(filterArgs.value(k_InitType_Key)); nx::core::Result resultOutputActions; std::vector preflightUpdatedValues; - auto& iDataArray = dataStructure.getDataRefAs(args.value(k_ArrayPath_Key)); + auto& iDataArray = dataStructure.getDataRefAs(filterArgs.value(k_ArrayPath_Key)); usize numComp = iDataArray.getNumberOfComponents(); // check that the values string is greater than max comps if(iDataArray.getDataType() == DataType::boolean) @@ -548,7 +182,7 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure switch(initializeTypeValue) { case InitializeType::FillValue: { - auto result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, iDataArray.getDataType(), numComp, args.value(k_InitValue_Key), 1); + auto result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, iDataArray.getDataType(), numComp, filterArgs.value(k_InitValue_Key), 1); if(result.outputActions.invalid()) { return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; @@ -559,7 +193,7 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure break; } case InitializeType::Incremental: { - auto result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, iDataArray.getDataType(), numComp, args.value(k_StartingFillValue_Key), 1); + auto result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, iDataArray.getDataType(), numComp, filterArgs.value(k_StartingFillValue_Key), 1); if(result.outputActions.invalid()) { return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; @@ -573,7 +207,7 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure updatedValStrm << "We detected that you are doing an incremental operation on a boolean array.\n"; updatedValStrm << "For the step values please enter uint8 values, preferably a 0 or 1 only.\n"; - switch(static_cast(args.value(k_StepOperation_Key))) + switch(static_cast(filterArgs.value(k_StepOperation_Key))) { case Addition: { updatedValStrm << "You have currently selected the addition operation.\nAny step value that is greater than 0 will cause all values to be 'true' after the first tuple, 'true' " @@ -595,7 +229,7 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure preflightUpdatedValues.push_back({"Boolean Incremental Nuances", updatedValStrm.str()}); - result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, DataType::uint8, numComp, args.value(k_StepValue_Key), 1); + result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, DataType::uint8, numComp, filterArgs.value(k_StepValue_Key), 1); if(result.outputActions.invalid()) { return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; @@ -603,13 +237,13 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure } else { - result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, iDataArray.getDataType(), numComp, args.value(k_StepValue_Key), 1); + result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, iDataArray.getDataType(), numComp, filterArgs.value(k_StepValue_Key), 1); if(result.outputActions.invalid()) { return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; } } - auto values = StringUtilities::split(args.value(k_StepValue_Key), ";", false); + auto values = StringUtilities::split(filterArgs.value(k_StepValue_Key), ";", false); std::vector zeroIdx; for(size_t i = 0; i < values.size(); i++) { @@ -629,13 +263,13 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure break; } case InitializeType::RangedRandom: { - auto result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, iDataArray.getDataType(), numComp, args.value(k_InitStartRange_Key), 1); + auto result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, iDataArray.getDataType(), numComp, filterArgs.value(k_InitStartRange_Key), 1); if(result.outputActions.invalid()) { return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; } - result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, iDataArray.getDataType(), numComp, args.value(k_InitEndRange_Key), 1); + result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, iDataArray.getDataType(), numComp, filterArgs.value(k_InitEndRange_Key), 1); if(result.outputActions.invalid()) { return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; @@ -649,7 +283,7 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure if(numComp == 1) { - if(args.value(k_StandardizeSeed_Key)) + if(filterArgs.value(k_StandardizeSeed_Key)) { operationNuancesStrm << fmt::format("You chose to standardize the seed for each component, but the array {} is a single component so it will not alter the randomization scheme.", iDataArray.getName()); @@ -657,7 +291,7 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure } else { - if(args.value(k_StandardizeSeed_Key)) + if(filterArgs.value(k_StandardizeSeed_Key)) { operationNuancesStrm << "This generates THE SAME sequences of random numbers for each component in the array based on one seed.\n"; operationNuancesStrm << "The resulting array will look like | 1,1,1 | 9,9,9 | ...\n"; @@ -679,13 +313,13 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure } //------------------------------------------------------------------------------ -Result<> InitializeDataFilter::executeImpl(DataStructure& dataStructure, const Arguments& args, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, +Result<> InitializeDataFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel) const { - auto initType = static_cast(args.value(k_InitType_Key)); + auto initType = static_cast(filterArgs.value(k_InitType_Key)); - auto seed = args.value(k_SeedValue_Key); - if(!args.value(k_UseSeed_Key)) + auto seed = filterArgs.value(k_SeedValue_Key); + if(!filterArgs.value(k_UseSeed_Key)) { seed = static_cast(std::chrono::steady_clock::now().time_since_epoch().count()); } @@ -693,25 +327,21 @@ Result<> InitializeDataFilter::executeImpl(DataStructure& dataStructure, const A if(initType == InitializeType::Random || initType == InitializeType::RangedRandom) { // Store Seed Value in Top Level Array - dataStructure.getDataRefAs(DataPath({args.value(k_SeedArrayName_Key)}))[0] = seed; + dataStructure.getDataRefAs(DataPath({filterArgs.value(k_SeedArrayName_Key)}))[0] = seed; } InitializeDataInputValues inputValues; - + inputValues.InputArrayPath = filterArgs.value(k_ArrayPath_Key); inputValues.initType = initType; - inputValues.stepType = static_cast(args.value(k_StepOperation_Key)); - inputValues.stringValues = StringUtilities::split(StringUtilities::trimmed(args.value(k_InitValue_Key)), k_DelimiterChar); - inputValues.startValues = StringUtilities::split(StringUtilities::trimmed(args.value(k_StartingFillValue_Key)), k_DelimiterChar); - inputValues.stepValues = StringUtilities::split(StringUtilities::trimmed(args.value(k_StepValue_Key)), k_DelimiterChar); + inputValues.stepType = static_cast(filterArgs.value(k_StepOperation_Key)); + inputValues.stringValues = StringUtilities::split(StringUtilities::trimmed(filterArgs.value(k_InitValue_Key)), k_DelimiterChar); + inputValues.startValues = StringUtilities::split(StringUtilities::trimmed(filterArgs.value(k_StartingFillValue_Key)), k_DelimiterChar); + inputValues.stepValues = StringUtilities::split(StringUtilities::trimmed(filterArgs.value(k_StepValue_Key)), k_DelimiterChar); inputValues.seed = seed; - inputValues.randBegin = StringUtilities::split(StringUtilities::trimmed(args.value(k_InitStartRange_Key)), k_DelimiterChar); - inputValues.randEnd = StringUtilities::split(StringUtilities::trimmed(args.value(k_InitEndRange_Key)), k_DelimiterChar); - inputValues.standardizeSeed = args.value(k_StandardizeSeed_Key); - - auto& iDataArray = dataStructure.getDataRefAs(args.value(k_ArrayPath_Key)); - - ExecuteDataFunction(::FillArrayFunctor{}, iDataArray.getDataType(), iDataArray, inputValues); + inputValues.randBegin = StringUtilities::split(StringUtilities::trimmed(filterArgs.value(k_InitStartRange_Key)), k_DelimiterChar); + inputValues.randEnd = StringUtilities::split(StringUtilities::trimmed(filterArgs.value(k_InitEndRange_Key)), k_DelimiterChar); + inputValues.standardizeSeed = filterArgs.value(k_StandardizeSeed_Key); - return {}; + return InitializeData(dataStructure, messageHandler, shouldCancel, &inputValues)(); } } // namespace nx::core