From af4f5c14d363fc9070802807661c6e254bb3dcc9 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Thu, 26 Sep 2024 11:20:39 -0400 Subject: [PATCH] Better preflight values for CreateDataArrayAdvanced & InitializeData. (#1084) Signed-off-by: Joey Kleingers --- .../Filters/Algorithms/InitializeData.cpp | 200 ++++++++++++++++++ .../Filters/Algorithms/InitializeData.hpp | 124 ++++++++++- .../Filters/CreateDataArrayAdvancedFilter.cpp | 177 +++------------- .../Filters/InitializeDataFilter.cpp | 133 ++++-------- 4 files changed, 386 insertions(+), 248 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.cpp index 5545a09a9f..391c1a9156 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.cpp @@ -304,8 +304,208 @@ struct FillArrayFunctor } }; +int64 CreateCompValFromStr(const std::string& s) +{ + return (StringUtilities::toLower(s) == "true") ? 1 : (StringUtilities::toLower(s) == "false") ? 0 : std::stoll(s); +} } // namespace +namespace nx +{ +namespace core +{ +std::string CreateCompValsStr(const std::vector& componentValues, usize numComps) +{ + const usize compValueVisibilityThresholdCount = 10; + const usize startEndEllipseValueCount = compValueVisibilityThresholdCount / 2; + + std::stringstream updatedValStrm; + auto cValueTokens = componentValues; + if(cValueTokens.size() == 1) + { + cValueTokens = std::vector(numComps, cValueTokens[0]); + } + + if(numComps <= compValueVisibilityThresholdCount) + { + auto initFillTokensStr = fmt::format("{}", fmt::join(cValueTokens, ",")); + updatedValStrm << fmt::format("|{}|", initFillTokensStr, numComps); + } + else + { + auto initFillTokensBeginStr = fmt::format("{}", fmt::join(cValueTokens.begin(), cValueTokens.begin() + startEndEllipseValueCount, ",")); + auto initFillTokensEndStr = fmt::format("{}", fmt::join(cValueTokens.end() - startEndEllipseValueCount, cValueTokens.end(), ",")); + updatedValStrm << fmt::format("|{} ... {}|", initFillTokensBeginStr, initFillTokensEndStr, numComps); + } + + return updatedValStrm.str(); +} + +std::string CreateCompValsStr(const std::vector& componentValuesStrs, usize numComps) +{ + std::vector componentValues; + componentValues.reserve(componentValues.size()); + std::transform(componentValuesStrs.begin(), componentValuesStrs.end(), std::back_inserter(componentValues), CreateCompValFromStr); + return CreateCompValsStr(componentValues, numComps); +} + +void CreateFillPreflightVals(const std::string& initFillValueStr, usize numComps, std::vector& preflightUpdatedValues) +{ + if(numComps <= 1) + { + return; + } + + std::stringstream updatedValStrm; + + auto initFillTokens = StringUtilities::split(initFillValueStr, std::vector{';'}, false); + if(initFillTokens.size() == 1) + { + updatedValStrm << "Each tuple will contain the same values for all components: "; + } + else + { + updatedValStrm << "Each tuple will contain different values for all components: "; + } + + updatedValStrm << CreateCompValsStr(initFillTokens, numComps); + + preflightUpdatedValues.push_back({"Tuple Details", updatedValStrm.str()}); +}; + +void CreateIncrementalPreflightVals(const std::string& initFillValueStr, usize stepOperation, const std::string& stepValueStr, usize numTuples, usize numComps, + std::vector& preflightUpdatedValues) +{ + std::stringstream ss; + + auto initFillTokens = StringUtilities::split(initFillValueStr, std::vector{';'}, false); + auto stepValueTokens = StringUtilities::split(stepValueStr, ";", false); + + if(numComps > 1) + { + if(initFillTokens.size() == 1) + { + ss << "The first tuple will contain the same values for all components: "; + } + else + { + ss << "The first tuple will contain different values for all components: "; + } + + ss << CreateCompValsStr(initFillTokens, numComps); + + if(stepOperation == StepType::Addition) + { + ss << fmt::format("\nThe components in each tuple will increment by the following: {}.", CreateCompValsStr(stepValueTokens, numComps)); + } + else + { + ss << fmt::format("\nThe components in each tuple will decrement by the following: {}.", CreateCompValsStr(stepValueTokens, numComps)); + } + } + else if(stepOperation == StepType::Addition) + { + ss << fmt::format("\nThe single component tuples will increment by {}.", stepValueTokens[0]); + } + else + { + + ss << fmt::format("\nThe single component tuples will decrement by {}.", stepValueTokens[0]); + } + + std::vector initFillValues; + initFillValues.reserve(initFillTokens.size()); + std::transform(initFillTokens.begin(), initFillTokens.end(), std::back_inserter(initFillValues), [](const std::string& s) -> int64 { return std::stoll(s); }); + std::vector stepValues; + stepValues.reserve(stepValueTokens.size()); + std::transform(stepValueTokens.begin(), stepValueTokens.end(), std::back_inserter(stepValues), [](const std::string& s) -> int64 { return std::stoll(s); }); + + ss << "\n\nTuples Preview:\n"; + const usize maxIterations = 3; + usize actualIterations = std::min(numTuples, maxIterations); + for(usize i = 0; i < actualIterations; ++i) + { + ss << fmt::format("{}\n", CreateCompValsStr(initFillValues, numComps)); + std::transform(initFillValues.begin(), initFillValues.end(), stepValues.begin(), initFillValues.begin(), + [stepOperation](int64 a, int64 b) { return (stepOperation == StepType::Addition) ? (a + b) : (a - b); }); + } + if(numTuples > maxIterations) + { + ss << "..."; + } + + std::vector zeroIdx; + for(usize i = 0; i < stepValueTokens.size(); i++) + { + if(stepValueTokens[i] == "0") + { + zeroIdx.push_back(i); + } + } + if(!zeroIdx.empty()) + { + + ss << "\n\nWarning: Component(s) at index(es) " << fmt::format("[{}]", fmt::join(zeroIdx, ",")) + << " have a ZERO value for the step value. The values at these component indexes will be unchanged from the starting value."; + } + + preflightUpdatedValues.push_back({"Tuple Details", ss.str()}); +} + +void CreateRandomPreflightVals(bool standardizeSeed, InitializeType initType, const std::string& initStartRange, const std::string& initEndRange, usize numTuples, usize numComps, + std::vector& preflightUpdatedValues) +{ + std::stringstream ss; + + if(numComps == 1) + { + if(initType == InitializeType::Random) + { + ss << fmt::format("The 1 component in each of the {} tuples will be filled with random values.", numTuples); + } + else if(initType == InitializeType::RangedRandom) + { + ss << fmt::format("The 1 component in each of the {} tuples will be filled with random values ranging from {} to {}.", numTuples, std::stoll(initStartRange), std::stoll(initEndRange)); + } + + if(standardizeSeed) + { + ss << "\n\nYou chose to standardize the seed for each component, but the array that will be created has a single component so it will not alter the randomization scheme."; + } + } + else + { + if(initType == InitializeType::Random) + { + ss << fmt::format("All {} components in each of the {} tuples will be filled with random values.", numComps, numTuples); + } + else if(initType == InitializeType::RangedRandom) + { + ss << fmt::format("All {} components in each of the {} tuples will be filled with random values ranging from these starting values:", numComps, numTuples); + auto startRangeTokens = StringUtilities::split(initStartRange, ";", false); + ss << "\n" << CreateCompValsStr(startRangeTokens, numComps); + ss << "\nto these ending values:"; + auto endRangeTokens = StringUtilities::split(initEndRange, ";", false); + ss << "\n" << CreateCompValsStr(endRangeTokens, numComps); + } + + if(standardizeSeed) + { + ss << "\n\nThis will generate THE SAME random value for all components in a given tuple, based on one seed."; + ss << "\nFor example: |1,1,1| |9,9,9| |4,4,4| ..."; + } + else + { + ss << "\n\nThis will generate DIFFERENT random values for each component in a given tuple, based on multiple seeds that are all modified versions of the original seed."; + ss << "\nFor example: |1,9,5| |7,1,6| |2,12,7| ..."; + } + } + + preflightUpdatedValues.push_back({"Tuple Details", ss.str()}); +} +} // namespace core +} // namespace nx + // ----------------------------------------------------------------------------- InitializeData::InitializeData(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, InitializeDataInputValues* inputValues) : m_DataStructure(dataStructure) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.hpp index 7403460ab6..8e92ce5320 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/InitializeData.hpp @@ -8,7 +8,6 @@ namespace nx::core { - constexpr char k_DelimiterChar = ';'; enum InitializeType : uint64 @@ -25,6 +24,90 @@ enum StepType : uint64 Subtraction }; +/** + * @brief Creates a formatted string representation of component values. + * + * This function generates a string by concatenating component values separated by commas. + * If the number of components exceeds a visibility threshold (10 by default), it displays + * only the first and last few values separated by ellipses. If a single component value is + * provided, it replicates that value for the specified number of components. + * + * @param componentValues A vector of integer component values. + * @param numComps The number of components to represent in the output string. + * @return A formatted string representing the component values. + */ +std::string CreateCompValsStr(const std::vector& componentValues, usize numComps); + +/** + * @brief Creates a formatted string representation of component values from string inputs. + * + * This function converts a vector of string component values to integers and then generates + * a formatted string representation using the integer version of CreateCompValsStr. + * If a single string component value is provided, it replicates that value for the specified + * number of components. + * + * @param componentValuesStrs A vector of string component values. + * @param numComps The number of components to represent in the output string. + * @return A formatted string representing the component values. + */ +std::string CreateCompValsStr(const std::vector& componentValuesStrs, usize numComps); + +/** + * @brief Generates preflight values for fill operations based on initial fill values. + * + * This function constructs a descriptive string detailing how tuples will be filled with + * component values. If a single initial fill value is provided, it applies the same value + * to all components; otherwise, it uses different values for each component. + * The generated description is appended to the provided preflightUpdatedValues vector. + * + * @param initFillValueStr A semicolon-separated string of initial fill values. + * @param numComps The number of components in each tuple. + * @param preflightUpdatedValues A reference to a vector where the generated preflight + * values will be stored. + */ +void CreateFillPreflightVals(const std::string& initFillValueStr, usize numComps, std::vector& preflightUpdatedValues); + +/** + * @brief Generates preflight values for incremental fill operations on tuples. + * + * This function creates a descriptive summary of how tuples will be initialized and incremented + * or decremented based on the provided step operation and step values. It includes a preview of + * the first few tuples and issues a warning if any step value is zero, indicating that the corresponding + * component values will remain unchanged. + * + * @param initFillValueStr A semicolon-separated string of initial fill values. + * @param stepOperation The operation type for stepping (e.g., addition or subtraction). + * @param stepValueStr A semicolon-separated string of step values for each component. + * @param numTuples The total number of tuples to generate. + * @param numComps The number of components in each tuple. + * @param preflightUpdatedValues A reference to a vector where the generated preflight + * values will be stored. + */ +void CreateIncrementalPreflightVals(const std::string& initFillValueStr, usize stepOperation, const std::string& stepValueStr, usize numTuples, usize numComps, + std::vector& preflightUpdatedValues); + +/** + * @brief Generates preflight values for random fill operations on tuples. + * + * This function constructs a descriptive summary of how tuples will be filled with random + * values, either within a specified range or without. It accounts for the number of components + * and tuples, and whether the random seed is standardized across components. For multiple + * components, it details whether values are generated independently or based on a single seed. + * + * @param standardizeSeed Indicates whether to use a standardized seed for all components. + * @param initType The type of initialization (e.g., random or ranged random). + * @param initStartRange A semicolon-separated string representing the starting range for + * random values (used if initType is ranged random). + * @param initEndRange A semicolon-separated string representing the ending range for + * random values (used if initType is ranged random). + * @param numTuples The total number of tuples to generate. + * @param numComps The number of components in each tuple. + * @param preflightUpdatedValues A reference to a vector where the generated preflight + * values will be stored. + */ +void CreateRandomPreflightVals(bool standardizeSeed, InitializeType initType, const std::string& initStartRange, const std::string& initEndRange, usize numTuples, usize numComps, + std::vector& preflightUpdatedValues); + struct SIMPLNXCORE_EXPORT InitializeDataInputValues { DataPath InputArrayPath; @@ -39,9 +122,48 @@ struct SIMPLNXCORE_EXPORT InitializeDataInputValues bool standardizeSeed; }; +/** + * @struct ValidateMultiInputFunctor + * @brief A functor for validating multi-component input strings. + * + * The `ValidateMultiInputFunctor` struct provides a templated functor to validate + * delimited input strings containing multiple components. It ensures that the input + * string: + * - Contains the expected number of components or an alternative acceptable number. + * - Does not contain empty values between delimiters. + * - Each component can be successfully converted to the specified type `T`. + * + * If the validation fails, the functor returns an error with a specific error code + * and descriptive message. Otherwise, it indicates successful validation. + */ struct SIMPLNXCORE_EXPORT ValidateMultiInputFunctor { // The single comp size validation defaults to off as size 0 is checked earlier in the function + + /** + * @brief Validates a delimited input string for the correct number of components and value types. + * + * This templated `operator()` performs the following validations on the input string: + * 1. Splits the input string `unfilteredStr` using the predefined delimiter `k_DelimiterChar`. + * 2. Checks if the resulting vector `splitVals` is empty. If empty, returns an error with code `-11610`. + * 3. Iterates through each split value to ensure: + * - No value is empty. If an empty value is found, returns an error with code `-11611`. + * - Each value can be converted to type `T`. If conversion fails, returns an error with code `-11612`. + * 4. Verifies the number of split components: + * - If the number of components matches `expectedComp`, validation is successful. + * - If `singleCompSize` is non-zero and matches the number of components, validation is successful. + * - If there is one extra component and the input string ends with a delimiter, returns an error with code `-11613`. + * - Otherwise, returns an error with code `-11614` indicating the number of components does not match expectations. + * + * @tparam T The type to which each component of the input string should be convertible. + * @param expectedComp The expected number of components in the input string. + * @param unfilteredStr The input string containing delimited components to be validated. + * @param singleCompSize An optional alternative number of components that is also considered valid. Defaults to `0`. + * + * @return An `IFilter::PreflightResult` indicating the success or failure of the validation. + * - Returns an empty result if validation is successful. + * - Returns an error result with a specific error code and message if validation fails. + */ template IFilter::PreflightResult operator()(const usize expectedComp, const std::string& unfilteredStr, const usize singleCompSize = 0) { diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayAdvancedFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayAdvancedFilter.cpp index 68669c6773..7902b0ec74 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayAdvancedFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/CreateDataArrayAdvancedFilter.cpp @@ -103,9 +103,9 @@ Parameters CreateDataArrayAdvancedFilter::parameters() const } 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/Decremental", "Random", "Random With Range"})); // sequence dependent DO NOT REORDER + 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")); @@ -114,8 +114,8 @@ Parameters CreateDataArrayAdvancedFilter::parameters() const k_StartingFillValue_Key, "Starting Value [Seperated with ;]", "The value to start incrementing from. Ex: 6;8;12 would increment a 3-component array starting at 6 for the first component, 8 for the 2nd, and 12 for the 3rd.", "0;1;2")); params.insert(std::make_unique(k_StepOperation_Key, "Step Operation", "The type of step operation to perform", static_cast(0), - ChoicesParameter::Choices{"Incrementing", "Decrementing"})); - params.insert(std::make_unique(k_StepValue_Key, "Step Value [Seperated with ;]", "The number to increment/decrement the fill value by", "1;1;1")); + ChoicesParameter::Choices{"Addition", "Subtraction"})); + params.insert(std::make_unique(k_StepValue_Key, "Step Value [Seperated with ;]", "The number to add/subtract 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)); @@ -171,6 +171,13 @@ IFilter::PreflightResult CreateDataArrayAdvancedFilter::preflightImpl(const Data auto dataArrayPath = filterArgs.value(k_DataPath_Key); auto tableData = filterArgs.value(k_TupleDims_Key); auto dataFormat = filterArgs.value(k_DataFormat_Key); + auto initFillValue = filterArgs.value(k_InitValue_Key); + auto initIncFillValue = filterArgs.value(k_StartingFillValue_Key); + auto stepValue = filterArgs.value(k_StepValue_Key); + auto stepOperation = filterArgs.value(k_StepOperation_Key); + auto initStartRange = filterArgs.value(k_InitStartRange_Key); + auto initEndRange = filterArgs.value(k_InitEndRange_Key); + auto standardizeSeed = filterArgs.value(k_StandardizeSeed_Key); nx::core::Result resultOutputActions; @@ -222,6 +229,8 @@ IFilter::PreflightResult CreateDataArrayAdvancedFilter::preflightImpl(const Data } } + usize numTuples = std::accumulate(tupleDims.begin(), tupleDims.end(), static_cast(1), std::multiplies<>()); + auto arrayDataType = ConvertNumericTypeToDataType(numericType); auto action = std::make_unique(ConvertNumericTypeToDataType(numericType), tupleDims, compDims, dataArrayPath, dataFormat); @@ -233,72 +242,6 @@ IFilter::PreflightResult CreateDataArrayAdvancedFilter::preflightImpl(const Data // nx::core::Result resultOutputActions; std::vector preflightUpdatedValues; - 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 {} separated by '{}'.\n", numComponents, - DataTypeToString(arrayDataType), k_DelimiterChar); - - // Define a threshold for displaying all components - const usize threshold = 10; - - updatedValStrm << "Example: "; - - if(numComponents <= threshold) - { - // Show all component values - for(usize comp = 0; comp < numComponents; comp++) - { - updatedValStrm << "1"; - - if(comp != numComponents - 1) - { - updatedValStrm << k_DelimiterChar; - } - } - } - else - { - // Show a limited number of component values followed by a summary - const usize displayCount = 10; - for(usize comp = 0; comp < displayCount; comp++) - { - updatedValStrm << "1"; - - if(comp != displayCount - 1) - { - updatedValStrm << k_DelimiterChar; - } - } - updatedValStrm << fmt::format(" ... {} more '1's", numComponents - displayCount); - } - - preflightUpdatedValues.push_back({"Multi-Component Note", updatedValStrm.str()}); - } - - std::stringstream operationNuancesStrm; - switch(initializeTypeValue) { case InitializeType::FillValue: { @@ -308,7 +251,8 @@ IFilter::PreflightResult CreateDataArrayAdvancedFilter::preflightImpl(const Data return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; } - operationNuancesStrm << "None to note"; + // Create the Fill Values preflight updated values + CreateFillPreflightVals(initFillValue, numComponents, preflightUpdatedValues); break; } @@ -319,67 +263,15 @@ IFilter::PreflightResult CreateDataArrayAdvancedFilter::preflightImpl(const Data 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++) + result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, arrayDataType, numComponents, filterArgs.value(k_StepValue_Key), 1); + if(result.outputActions.invalid()) { - if(values[i] == "0") - { - zeroIdx.push_back(i); - } + return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; } - 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 | ..."; - } + // Create the Incremental/Decremental Values preflight updated values + CreateIncrementalPreflightVals(initIncFillValue, stepOperation, stepValue, numTuples, numComponents, preflightUpdatedValues); + break; } case InitializeType::RangedRandom: { @@ -401,34 +293,13 @@ IFilter::PreflightResult CreateDataArrayAdvancedFilter::preflightImpl(const Data 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"; - } - } + // Create the Random Values preflight updated values + CreateRandomPreflightVals(standardizeSeed, initializeTypeValue, initStartRange, initEndRange, numTuples, numComponents, preflightUpdatedValues); break; } } - preflightUpdatedValues.push_back({"Operation Nuances", operationNuancesStrm.str()}); - return {std::move(resultOutputActions), std::move(preflightUpdatedValues)}; } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/InitializeDataFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/InitializeDataFilter.cpp index f69b25e01b..13cbf34128 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/InitializeDataFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/InitializeDataFilter.cpp @@ -65,17 +65,17 @@ Parameters InitializeDataFilter::parameters() const params.insertSeparator(Parameters::Separator{"Input Parameter(s)"}); - 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/Decremental", "Random", "Random With Range"})); // sequence dependent DO NOT REORDER + 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{"Incrementing", "Decrementing"})); - params.insert(std::make_unique(k_StepValue_Key, "Step Value [Seperated with ;]", "The number to increment/decrement the fill value by", "1;1;1")); + ChoicesParameter::Choices{"Addition", "Subtraction"})); + params.insert(std::make_unique(k_StepValue_Key, "Step Value [Seperated with ;]", "The number to add/subtract 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)); @@ -128,6 +128,13 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure { auto seedArrayNameValue = filterArgs.value(k_SeedArrayName_Key); auto initializeTypeValue = static_cast(filterArgs.value(k_InitType_Key)); + auto initFillValue = filterArgs.value(k_InitValue_Key); + auto initIncFillValue = filterArgs.value(k_StartingFillValue_Key); + auto stepValue = filterArgs.value(k_StepValue_Key); + auto stepOperation = filterArgs.value(k_StepOperation_Key); + auto initStartRange = filterArgs.value(k_InitStartRange_Key); + auto initEndRange = filterArgs.value(k_InitEndRange_Key); + auto standardizeSeed = filterArgs.value(k_StandardizeSeed_Key); nx::core::Result resultOutputActions; std::vector preflightUpdatedValues; @@ -137,46 +144,21 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure if(iDataArray.getDataType() == DataType::boolean) { - std::stringstream updatedValStrm; + std::stringstream ss; - 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"; + ss << "We detected that you are doing an operation on a boolean array.\n"; + ss << "The ONLY two ways to specify a 'false' boolean value are as follows:\n"; + ss << "- boolean value string types as follows ignoring apostrophe marks: 'False', 'FALSE', 'false'\n"; + ss << "- 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"; + ss << "ANY OTHER string or number WILL BE 'true', although it is good practice to define true values as follows:\n"; + ss << "- boolean value string types as follows ignoring apostrophe marks: 'True', 'TRUE', 'true'\n"; + ss << "- all well formed integers and well formed floating point definitions of 1"; - preflightUpdatedValues.push_back({"Boolean Note", updatedValStrm.str()}); + preflightUpdatedValues.push_back({"Boolean Note", ss.str()}); } - if(numComp > 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", numComp, - DataTypeToString(iDataArray.getDataType()), k_DelimiterChar); - updatedValStrm << "Example: "; - - for(usize comp = 0; comp < numComp; comp++) - { - updatedValStrm << "1"; - - if(comp != numComp - 1) - { - updatedValStrm << k_DelimiterChar; - } - } - - preflightUpdatedValues.push_back({"Multi-Component Note", updatedValStrm.str()}); - } - - std::stringstream operationNuancesStrm; + usize numTuples = iDataArray.getNumberOfTuples(); switch(initializeTypeValue) { @@ -187,7 +169,7 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure return {MergeResults(result.outputActions, std::move(resultOutputActions)), std::move(preflightUpdatedValues)}; } - operationNuancesStrm << "None to note"; + CreateFillPreflightVals(initFillValue, numComp, preflightUpdatedValues); break; } @@ -201,32 +183,31 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure if(iDataArray.getDataType() == DataType::boolean) { // custom bool checks here - std::stringstream updatedValStrm; + std::stringstream ss; - 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"; + ss << "A boolean array is being initialized so please enter unsigned 8-bit integer 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 | ... |"; + ss << "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"; + ss << "The two possibilities:\n"; + ss << "- If your start value is 'false' and step value > 0, the array will initialize to | false | true | true | ... |\n"; + ss << "- 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 | ... |"; + ss << "You have currently selected the subtraction 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"; + ss << "The two possibilities:\n"; + ss << "- If your start value is 'true' and step value > 0, the array will initialize to | true | false | false | ... |\n"; + ss << "- 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()}); + preflightUpdatedValues.push_back({"Boolean Incremental Nuances", ss.str()}); result = ExecuteDataFunction(::ValidateMultiInputFunctor{}, DataType::uint8, numComp, filterArgs.value(k_StepValue_Key), 1); if(result.outputActions.invalid()) @@ -242,23 +223,9 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure 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 | ..."; - } + CreateIncrementalPreflightVals(initIncFillValue, stepOperation, stepValue, numTuples, numComp, preflightUpdatedValues); + break; } case InitializeType::RangedRandom: { @@ -280,34 +247,12 @@ IFilter::PreflightResult InitializeDataFilter::preflightImpl(const DataStructure auto createAction = std::make_unique(DataType::uint64, std::vector{1}, std::vector{1}, DataPath({seedArrayNameValue})); resultOutputActions.value().appendAction(std::move(createAction)); - if(numComp == 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.", - iDataArray.getName()); - } - } - 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"; - } - } + CreateRandomPreflightVals(standardizeSeed, initializeTypeValue, initStartRange, initEndRange, numTuples, numComp, preflightUpdatedValues); break; } } - preflightUpdatedValues.push_back({"Operation Nuances", operationNuancesStrm.str()}); - return {std::move(resultOutputActions), std::move(preflightUpdatedValues)}; }