diff --git a/src/libs/ascent/runtimes/expressions/ascent_expression_jit_filters.cpp b/src/libs/ascent/runtimes/expressions/ascent_expression_jit_filters.cpp index 82584c780..e7f35eae6 100644 --- a/src/libs/ascent/runtimes/expressions/ascent_expression_jit_filters.cpp +++ b/src/libs/ascent/runtimes/expressions/ascent_expression_jit_filters.cpp @@ -149,9 +149,7 @@ ExprJitFilter::declare_interface(Node &i) filters::string_schema(param_schema["properties/func"]); filters::string_schema(param_schema["properties/filter_name"]); - conduit::Node &inputs_schema = filters::array_schema(param_schema["properties/inputs"]); - inputs_schema["minItems"] = num_inputs; - inputs_schema["maxItems"] = num_inputs; + conduit::Node &inputs_schema = filters::array_schema(param_schema["properties/inputs"], conduit::Node(), num_inputs, num_inputs); param_schema["required"].append() = "func"; param_schema["required"].append() = "filter_name"; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_adios2_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_adios2_filters.cpp index 0a9597010..eaed08a9e 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_adios2_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_adios2_filters.cpp @@ -24,6 +24,7 @@ //----------------------------------------------------------------------------- #include #include +#include #include #include @@ -114,43 +115,26 @@ ADIOS2::declare_interface(Node &i) i["type_name"] = "adios2"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} -//----------------------------------------------------------------------------- -bool -ADIOS2::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - bool res = true; - if (!params.has_child("filename") || - !params["filename"].dtype().is_string()) - { - info["errors"].append() = "missing required entry 'filename'"; - res = false; - } + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; - if (!params.has_child("engine") || - !params["engine"].dtype().is_string()) - { - info["errors"].append() = "missing required entry 'engine'"; - res = false; - } + string_schema(param_schema["properties/filename"]); + string_schema(param_schema["properties/engine"]); - std::string engineType = params["engine"].as_string(); - if (engineType != "BPFile" && engineType != "SST") - { - info["errors"].append() = "unsupported engine type: " + engineType; - res = false; - } + conduit::Node &bpfile_schema = param_schema["oneOf"].append(); + bpfile_schema["type"] = "object"; + string_schema(bpfile_schema["properties/engine"]); + bpfile_schema["properties/engine/constraints/const"] = "BPFile"; - std::string fileName = params["filename"].as_string(); - if (engineType == "SST" && fileName.find("/") != std::string::npos ) - { - info["errors"].append() = "filename with directory not supported for SST engine"; - res = false; - } + conduit::Node &sst_schema = param_schema["oneOf"].append(); + sst_schema["type"] = "object"; + string_schema(sst_schema["properties/engine"]); + sst_schema["properties/engine/constraints/const"] = "SST"; - return res; + conduit::Node &fname = string_schema(sst_schema["properties/filename"]); + fname["pattern"] = "^[^/]*$"; } //----------------------------------------------------------------------------- diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_adios2_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_adios2_filters.hpp index 3f74c5ab1..d3905a660 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_adios2_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_adios2_filters.hpp @@ -52,8 +52,6 @@ class ADIOS2 : public ::flow::Filter ~ADIOS2(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); private: diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_compose.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_compose.cpp index 0890afc10..5e02a763f 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_compose.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_compose.cpp @@ -42,23 +42,21 @@ void ascent::runtime::filters::BFlowCompose::declare_interface(conduit::Node &i) i["type_name"] = "bflow_comp"; i["port_names"].append() = "in"; i["output_port"] = "false"; // true -- means filter, false -- means extract -} - -//----------------------------------------------------------------------------- - -bool ascent::runtime::filters::BFlowCompose::verify_params(const conduit::Node ¶ms, conduit::Node &info) -{ - info.reset(); - bool res = true; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; - res &= check_string("color_field", params, info, true); - res &= check_string("depth_field", params, info, true); - res &= check_string("image_prefix", params, info, true); - res &= check_numeric("compositing", params, info, true); - res &= check_numeric("fanin", params, info, false); + string_schema(param_schema["properties/color_field"]); + string_schema(param_schema["properties/depth_field"]); + string_schema(param_schema["properties/image_prefix"]); + number_schema(param_schema["properties/compositing"]); + number_schema(param_schema["properties/fanin"]); - return res; + param_schema["required"].append() = "color_field"; + param_schema["required"].append() = "depth_field"; + param_schema["required"].append() = "image_prefix"; + param_schema["required"].append() = "compositing"; } //----------------------------------------------------------------------------- diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_filters.hpp index 07e9eaad4..738b80aea 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_filters.hpp @@ -37,8 +37,6 @@ class BFlowPmt : public ::flow::Filter virtual ~BFlowPmt() {} virtual void declare_interface(conduit::Node &i) override; - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info) override; virtual void execute() override; }; @@ -53,8 +51,6 @@ class BFlowCompose : public ::flow::Filter virtual ~BFlowCompose() {} virtual void declare_interface(conduit::Node &i) override; - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info) override; virtual void execute() override; }; @@ -67,8 +63,6 @@ class BFlowIso : public ::flow::Filter virtual ~BFlowIso() {} virtual void declare_interface(conduit::Node &i) override; - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info) override; virtual void execute() override; }; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_iso.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_iso.cpp index 76dc00fec..b3bf98db8 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_iso.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_iso.cpp @@ -530,25 +530,21 @@ void ascent::runtime::filters::BFlowIso::declare_interface(conduit::Node &i) i["type_name"] = "bflow_iso"; i["port_names"].append() = "in"; i["output_port"] = "false"; // true -- means filter, false -- means extract -} -//----------------------------------------------------------------------------- + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; -bool ascent::runtime::filters::BFlowIso::verify_params(const conduit::Node ¶ms, conduit::Node &info) -{ - info.reset(); + string_schema(param_schema["properties/field"]); + number_schema(param_schema["properties/iso_values"]); + string_schema(param_schema["properties/image_name"]); + number_schema(param_schema["properties/radices"]); + number_schema(param_schema["properties/width"]); + number_schema(param_schema["properties/height"]); - bool res = true; - - res &= check_string("field", params, info, true); - res &= check_numeric("iso_values", params, info, true); - res &= check_string("image_name", params, info, true); - res &= check_numeric("radices", params, info, false); - res &= check_numeric("width", params, info, false); - res &= check_numeric("height", params, info, false); - // res &= check_string("col_field", params, info, true); - - return res; + param_schema["required"].append() = "field"; + param_schema["required"].append() = "iso_values"; + param_schema["required"].append() = "image_name"; } //----------------------------------------------------------------------------- diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_pmt.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_pmt.cpp index 3eb6236df..74fe44acf 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_pmt.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_babelflow_pmt.cpp @@ -1464,6 +1464,21 @@ void ascent::runtime::filters::BFlowPmt::declare_interface(conduit::Node &i) i["type_name"] = "bflow_pmt"; i["port_names"].append() = "in"; i["output_port"] = "true"; // true -- means filter, false -- means extract + + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + + string_schema(param_schema["properties/field"]); + number_schema(param_schema["properties/fanin"]); + number_schema(param_schema["properties/threshold"]); + number_schema(param_schema["properties/gen_segment"]); + number_schema(param_schema["properties/ugrid_select"]); + + param_schema["required"].append() = "field"; + param_schema["required"].append() = "fanin"; + param_schema["required"].append() = "threshold"; + param_schema["required"].append() = "gen_segment"; } //----------------------------------------------------------------------------- @@ -1847,20 +1862,3 @@ void ascent::runtime::filters::BFlowPmt::execute() set_output(d_input); } - -//----------------------------------------------------------------------------- - -bool ascent::runtime::filters::BFlowPmt::verify_params(const conduit::Node ¶ms, conduit::Node &info) -{ - info.reset(); - - bool res = true; - - res &= check_string("field", params, info, true); - res &= check_numeric("fanin", params, info, true); - res &= check_numeric("threshold", params, info, true); - res &= check_numeric("gen_segment", params, info, true); - res &= check_numeric("ugrid_select", params, info, false); - - return res; -} diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp index 1189463cc..812c33223 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp @@ -103,23 +103,13 @@ BlueprintVerify::declare_interface(Node &i) i["type_name"] = "blueprint_verify"; i["port_names"].append() = "in"; i["output_port"] = "true"; -} -//----------------------------------------------------------------------------- -bool -BlueprintVerify::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = true; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; - if(! params.has_child("protocol") || - ! params["protocol"].dtype().is_string() ) - { - info["errors"].append() = "Missing required string parameter 'protocol'"; - } - - return res; + string_schema(param_schema["properties/protocol"]); + param_schema["required"].append() = "protocol"; } @@ -241,19 +231,6 @@ ConduitExtract::declare_interface(Node &i) i["output_port"] = "false"; } -//----------------------------------------------------------------------------- -bool -ConduitExtract::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = true; - - // so far, no params - - return res; -} - //----------------------------------------------------------------------------- void ConduitExtract::execute() @@ -310,73 +287,40 @@ BlueprintPartition::declare_interface(Node &i) i["type_name"] = "blueprint_data_partition"; i["port_names"].append() = "in"; i["output_port"] = "true"; -} -//----------------------------------------------------------------------------- -bool -BlueprintPartition::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = true; - - res &= check_numeric("target",params, info, false, false); - - if(params.has_child("selections")) - { - res &= check_string("selections/type",params, info, true); - //domain_id can be int or "any" - res &= (check_string("selections/domain_id",params, info, false) || check_numeric("selections/domain_id", params, info, false, false)); - res &= check_string("selections/topology",params, info, false); - } - - if(params.has_child("fields")) - { - if(!params["fields"].dtype().is_list()) - { - res = false; - info["errors"].append() = "fields is not a list"; - } - } - - res &= check_numeric("mapping",params, info, false, false); - res &= check_numeric("merge_tolerance",params, info, false, false); - res &= check_numeric("build_adjsets",params, info, false, false); - res &= check_string("original_element_ids",params, info, false); - res &= check_string("original_vertex_ids",params, info, false); - - std::vector valid_paths; - valid_paths.push_back("target"); - valid_paths.push_back("selections/type"); - valid_paths.push_back("selections/domain_id"); - valid_paths.push_back("selections/field"); - valid_paths.push_back("selections/topology"); - valid_paths.push_back("selections/start"); - valid_paths.push_back("selections/end"); - valid_paths.push_back("selections/elements"); - valid_paths.push_back("selections/ranges"); - valid_paths.push_back("selections/field"); - valid_paths.push_back("mapping"); - valid_paths.push_back("merge_tolerance"); - valid_paths.push_back("build_adjsets"); - valid_paths.push_back("original_element_ids"); - valid_paths.push_back("original_vertex_ids"); - valid_paths.push_back("distributed"); - - std::vector ingore_paths = {"fields"}; - - std::string surprises = surprise_check(valid_paths,ingore_paths, params); - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } - - return res; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + + number_schema(param_schema["properties/target"]); + array_schema(param_schema["properties/fields"]); + number_schema(param_schema["properties/mapping"]); + number_schema(param_schema["properties/merge_tolerance"]); + number_schema(param_schema["properties/build_adjsets"]); + string_schema(param_schema["properties/original_element_ids"]); + string_schema(param_schema["properties/original_vertex_ids"]); + ignore_schema(param_schema["properties/distributed"]); + + // --- selections --- + conduit::Node &selections_schema = param_schema["properties/selections"]; + selections_schema["type"] = "object"; + selections_schema["additionalProperties"] = false; + string_schema(selections_schema["properties/type"]); + string_schema(selections_schema["properties/topology"]); + ignore_schema(selections_schema["properties/field"]); + ignore_schema(selections_schema["properties/start"]); + ignore_schema(selections_schema["properties/end"]); + ignore_schema(selections_schema["properties/elements"]); + ignore_schema(selections_schema["properties/ranges"]); + selections_schema["required"].append() = "type"; + + conduit::Node domain_id_schema = selections_schema["properties/domain_id"]; + domain_id_schema["type"] = "object"; + string_schema(domain_id_schema["oneOf"].append()); + number_schema(domain_id_schema["oneOf"].append()); } - //----------------------------------------------------------------------------- void BlueprintPartition::execute() @@ -467,114 +411,47 @@ DataBinning::declare_interface(Node &i) i["type_name"] = "data_binning"; i["port_names"].append() = "in"; i["output_port"] = "true"; -} - -//----------------------------------------------------------------------------- -bool -DataBinning::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = true; - - if(!params.has_path("reduction_op")) - { - res = false; - info["errors"].append() = "Missing 'reduction_op'"; - } - - // note: `var` is deprecated, new arg reduction_field - if(!params.has_path("reduction_field")) - { - if(!params.has_path("var")) - { - res = false; - info["errors"].append() = "Missing 'reduction_field'"; - } - } - - std::vector valid_paths; - valid_paths.push_back("reduction_op"); - valid_paths.push_back("reduction_field"); - valid_paths.push_back("empty_bin_val"); - valid_paths.push_back("output_type"); - valid_paths.push_back("output_field"); - valid_paths.push_back("var"); - - std::vector ignore_paths; - ignore_paths.push_back("axes"); - - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if(!params.has_path("output_field")) - { - res = false; - info["errors"].append() = "Missing param 'output_field'"; - } - - if(!params.has_path("axes")) - { - res = false; - info["errors"].append() = "Missing binning axes"; - } - else if(!params["axes"].dtype().is_list()) - { - res = false; - info["errors"].append() = "Axes is not a list"; - } - else - { - const int num_axes = params["axes"].number_of_children(); - if(num_axes < 1 || num_axes > 3) - { - res = false; - info["errors"].append() = "Number of axes must be between 1 and 3"; - } - else - { - for(int i = 0; i < num_axes; ++i) - { - const conduit::Node &axis = params["axes"].child(i); - if(!axis.has_path("num_bins")) - { - res = false; - info["errors"].append() = "Axis missing 'num_bins'"; - } - - if(!axis.has_child("field")) - { - if(!axis.has_child("var")) - { - std::ostringstream oss; - oss << "Axis " << i << " missing 'field' parameter"; - res = false; - info["errors"].append() = oss.str(); - } - } - - std::vector avalid_paths; - avalid_paths.push_back("min_val"); - avalid_paths.push_back("max_val"); - avalid_paths.push_back("num_bins"); - avalid_paths.push_back("clamp"); - avalid_paths.push_back("field"); - avalid_paths.push_back("var"); - - surprises += surprise_check(avalid_paths, axis); - } - } - } - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } - return res; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + param_schema["constraints/exclusiveChildren"].append() = "reduction_field"; + param_schema["constraints/exclusiveChildren"].append() = "var"; + param_schema["constraints/allowNoneInExclusiveGroup"] = false; + + ignore_schema(param_schema["properties/reduction_op"]); + ignore_schema(param_schema["properties/reduction_field"]); + ignore_schema(param_schema["properties/empty_bin_val"]); + string_schema(param_schema["properties/output_type"]); + ignore_schema(param_schema["properties/output_field"]); + ignore_schema(param_schema["properties/var"]); + + // --- Axes --- + { + conduit::Node single_axis_schema; + single_axis_schema["type"] = "object"; + single_axis_schema["additionalProperties"] = false; + single_axis_schema["constraints/exclusiveChildren"].append() = "field"; + single_axis_schema["constraints/exclusiveChildren"].append() = "var"; + single_axis_schema["constraints/allowNoneInExclusiveGroup"] = false; + + number_schema(single_axis_schema["properties/min_val"], true); + number_schema(single_axis_schema["properties/max_val"], true); + number_schema(single_axis_schema["properties/num_bins"], true); + number_schema(single_axis_schema["properties/clamp"], true); + number_schema(single_axis_schema["properties/field"], true); + number_schema(single_axis_schema["properties/var"], true); + single_axis_schema["required"].append() = "num_bins"; + + conduit::Node axes_schema = array_schema(param_schema["properties/axes"], single_axis_schema, 1, 3); + } + + param_schema["required"].append() = "reduction_op"; + param_schema["required"].append() = "output_field"; + param_schema["required"].append() = "axes"; } - //----------------------------------------------------------------------------- void DataBinning::execute() @@ -794,50 +671,17 @@ AddFields::declare_interface(Node &i) i["type_name"] = "add_fields"; i["port_names"].append() = "in"; i["output_port"] = "true"; -} -//----------------------------------------------------------------------------- -bool -AddFields::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = true; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + string_schema(param_schema["properties/output_field"]); + array_schema(param_schema["properties/fields"]); - if(!params.has_path("output_field")) - { - res = false; - info["errors"].append() = "Missing param 'output_field'"; - } - - if(!params.has_path("fields")) - { - res = false; - info["errors"].append() = "Missing 'fields'"; - } - else if(!params["fields"].dtype().is_list()) - { - res = false; - info["errors"].append() = "fields is not a list"; - } - - std::vector valid_paths; - std::vector ignore_paths; - valid_paths.push_back("fields"); - valid_paths.push_back("output_field"); - ignore_paths.push_back("fields"); - - - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } - - return res; + param_schema["required"].append() = "output_field"; + param_schema["required"].append() = "fields"; } //----------------------------------------------------------------------------- @@ -902,51 +746,19 @@ PowerOfField::declare_interface(Node &i) i["type_name"] = "power_of_field"; i["port_names"].append() = "in"; i["output_port"] = "true"; -} - -//----------------------------------------------------------------------------- -bool -PowerOfField::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = true; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - if(!params.has_path("output_field")) - { - res = false; - info["errors"].append() = "Missing param 'output_field'"; - } - - if(!params.has_path("field")) - { - res = false; - info["errors"].append() = "Missing param 'field'"; - } - - if(!params.has_path("exponent")) - { - res = false; - info["errors"].append() = "Missing param 'exponent'"; - } - - std::vector valid_paths; - std::vector ignore_paths; - valid_paths.push_back("field"); - valid_paths.push_back("exponent"); - valid_paths.push_back("output_field"); - - - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } + string_schema(param_schema["properties/output_field"]); + string_schema(param_schema["properties/field"]); + number_schema(param_schema["properties/exponent"]); - return res; + param_schema["required"].append() = "output_field"; + param_schema["required"].append() = "field"; + param_schema["required"].append() = "exponent"; } //----------------------------------------------------------------------------- diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.hpp index 3e0b39f71..8b6a17d8c 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.hpp @@ -51,8 +51,6 @@ class ASCENT_API BlueprintVerify : public ::flow::Filter ~BlueprintVerify(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -66,8 +64,6 @@ class ASCENT_API ConduitExtract: public ::flow::Filter ~ConduitExtract(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -80,8 +76,6 @@ class ASCENT_API BlueprintPartition : public ::flow::Filter ~BlueprintPartition(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -93,8 +87,6 @@ class ASCENT_API DataBinning : public ::flow::Filter ~DataBinning(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -106,8 +98,6 @@ class ASCENT_API AddFields : public ::flow::Filter ~AddFields(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -119,8 +109,6 @@ class ASCENT_API PowerOfField : public ::flow::Filter ~PowerOfField(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_command_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_command_filters.cpp index bab0686ba..977626948 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_command_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_command_filters.cpp @@ -78,57 +78,18 @@ Command::declare_interface(Node &i) i["type_name"] = "command"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} - -//----------------------------------------------------------------------------- -bool -Command::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - - bool has_callback = params.has_path("callback"); - bool has_shell_command = params.has_path("shell_command"); - - bool res = false; - if (!has_callback && !has_shell_command) - { - info["errors"].append() = "There was no callback or shell command defined"; - } - else if (has_callback && has_shell_command) - { - info["errors"].append() = "Both a callback and shell command are " - "present. Choose one or the other."; - } - else if(has_callback && !params["callback"].dtype().is_string()) - { - info["errors"].append() = "Callbacks must be a string"; - } - else if(has_shell_command && !params["shell_command"].dtype().is_string()) - { - info["errors"].append() = "Shell commands must be a string"; - } - else - { - res = true; - } - - std::vector valid_paths; - valid_paths.push_back("callback"); - valid_paths.push_back("shell_command"); - valid_paths.push_back("mpi_behavior"); - - std::vector ignore_paths; - - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if (surprises != "") - { - res = false; - info["errors"].append() = surprises; - } - return res; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + param_schema["constraints/exclusiveChildren"].append() = "callback"; + param_schema["constraints/exclusiveChildren"].append() = "shell_command"; + param_schema["constraints/allowNoneInExclusiveGroup"] = false; + + string_schema(param_schema["properties/callback"]); + string_schema(param_schema["properties/shell_command"]); + string_schema(param_schema["properties/mpi_behavior"]); } //----------------------------------------------------------------------------- diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_command_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_command_filters.hpp index 66e61b842..b4bd61927 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_command_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_command_filters.hpp @@ -48,8 +48,6 @@ class ASCENT_API Command : public ::flow::Filter Command(); ~Command(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); void static execute_command_list(const std::vector commands, diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.cpp index 0f0b44504..92d764339 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.cpp @@ -155,71 +155,53 @@ dray::Collection boundary(dray::Collection &collection) return bounder.execute(collection); } -std::string -dray_color_table_surprises(const conduit::Node &color_table) -{ - std::string surprises; - - std::vector valid_paths; - valid_paths.push_back("name"); - valid_paths.push_back("reverse"); - - std::vector ignore_paths; - ignore_paths.push_back("control_points"); - - surprises += surprise_check(valid_paths, ignore_paths, color_table); - if(color_table.has_path("control_points")) - { - const Node &control_points_node = color_table.fetch("control_points"); - - if (control_points_node.dtype().is_list()) - { - std::vector c_valid_paths; - c_valid_paths.push_back("type"); - c_valid_paths.push_back("alpha"); - c_valid_paths.push_back("color"); - c_valid_paths.push_back("position"); - - const conduit::Node &control_points = color_table["control_points"]; - const int num_points = control_points.number_of_children(); - for(int i = 0; i < num_points; ++i) - { - const conduit::Node &point = control_points.child(i); - surprises += surprise_check(c_valid_paths, point); - } - } - else if (control_points_node.dtype().is_object()) - { - // Valid path options for the compressed control points input format - std::vector c_valid_paths; - c_valid_paths.push_back("r"); - c_valid_paths.push_back("g"); - c_valid_paths.push_back("b"); - c_valid_paths.push_back("a"); - c_valid_paths.push_back("position"); - - - surprises += surprise_check(c_valid_paths, control_points_node); +void dray_color_table_schema(conduit::Node ¶m_schema) { + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + + string_schema(param_schema["properties/name"]); + bool_schema(param_schema["properties/reverse"]); + + // --- Control Points --- + { + conduit::Node &control_points_schema = param_schema["properties/control_points"]; + + conduit::Node &cp_compressed_schema = control_points_schema["oneOf"].append(); + cp_compressed_schema["type"] = "object"; + cp_compressed_schema["additionalProperties"] = false; + ignore_schema(cp_compressed_schema["properties/r"]); + ignore_schema(cp_compressed_schema["properties/g"]); + ignore_schema(cp_compressed_schema["properties/b"]); + ignore_schema(cp_compressed_schema["properties/a"]); + ignore_schema(cp_compressed_schema["properties/position"]); + cp_compressed_schema["constraints/forbid"].append() = "type"; + cp_compressed_schema["constraints/forbid"].append() = "alpha"; + cp_compressed_schema["constraints/forbid"].append() = "color"; + + conduit::Node cp_list_item_schema; + cp_list_item_schema["type"] = "object"; + cp_list_item_schema["additionalProperties"] = false; + ignore_schema(cp_list_item_schema["properties/type"]); + ignore_schema(cp_list_item_schema["properties/alpha"]); + ignore_schema(cp_list_item_schema["properties/color"]); + ignore_schema(cp_list_item_schema["properties/position"]); + cp_list_item_schema["constraints/forbid"].append() = "r"; + cp_list_item_schema["constraints/forbid"].append() = "g"; + cp_list_item_schema["constraints/forbid"].append() = "b"; + cp_list_item_schema["constraints/forbid"].append() = "a"; + + array_schema(control_points_schema["oneOf"].append(), cp_list_item_schema); } - } - - return surprises; } -std::string -dray_load_balance_surprises(const conduit::Node &load_balance) -{ - std::string surprises; - - std::vector valid_paths; - valid_paths.push_back("enabled"); - valid_paths.push_back("factor"); - valid_paths.push_back("threshold"); - valid_paths.push_back("use_prefix"); +void dray_load_balance_schema(conduit::Node ¶m_schema) { + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - surprises += surprise_check(valid_paths, load_balance); - - return surprises; + bool_schema(param_schema["properties/enabled"]); + number_schema(param_schema["properties/factor"]); + number_schema(param_schema["properties/threshold"]); + bool_schema(param_schema["properties/use_prefix"]); } dray::Vec @@ -1079,30 +1061,6 @@ class DrayCinemaDatabases std::map DrayCinemaDatabases::m_databases; - - -bool check_image_names(const conduit::Node ¶ms, conduit::Node &info) -{ - bool res = true; - if(!params.has_path("image_prefix") && - !params.has_path("camera/db_name")) - { - res = false; - info.append() = "Devil ray rendering paths must include either " - "a 'image_prefix' (if its a single image) or a " - "'camera/db_name' (if using a cinema camere)"; - } - if(params.has_path("image_prefix") && - params.has_path("camera/db_name")) - { - res = false; - info.append() = "Devil ray rendering paths cannot use both " - "a 'image_prefix' (if its a single image) and a " - "'camera/db_name' (if using a cinema camere)"; - } - return res; -} - void parse_params(const conduit::Node ¶ms, dray::Collection *dcol, @@ -1268,62 +1226,49 @@ DRayPseudocolor::declare_interface(Node &i) i["type_name"] = "dray_pseudocolor"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} -//----------------------------------------------------------------------------- -bool -DRayPseudocolor::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - - bool res = true; - - res &= check_string("field",params, info, true); - res &= detail::check_image_names(params, info); - res &= check_numeric("min_value",params, info, false); - res &= check_numeric("max_value",params, info, false); - res &= check_numeric("image_width",params, info, false); - res &= check_numeric("image_height",params, info, false); - res &= check_string("log_scale",params, info, false); - res &= check_string("annotations",params, info, false); - - std::vector valid_paths; - std::vector ignore_paths; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - valid_paths.push_back("field"); - valid_paths.push_back("image_prefix"); - valid_paths.push_back("min_value"); - valid_paths.push_back("max_value"); - valid_paths.push_back("image_width"); - valid_paths.push_back("image_height"); - valid_paths.push_back("log_scale"); - valid_paths.push_back("annotations"); + string_schema(param_schema["properties/field"]); + string_schema(param_schema["properties/image_prefix"]); + number_schema(param_schema["properties/min_value"]); + number_schema(param_schema["properties/max_value"]); + number_schema(param_schema["properties/image_width"]); + number_schema(param_schema["properties/image_height"]); + string_schema(param_schema["properties/log_scale"]); + string_schema(param_schema["properties/annotations"]); + string_schema(param_schema["properties/draw_mesh"]); + number_schema(param_schema["properties/line_thickness"]); + number_schema(param_schema["properties/line_color"]); + ignore_schema(param_schema["properties/camera"]); - // filter knobs - valid_paths.push_back("draw_mesh"); - valid_paths.push_back("line_thickness"); - valid_paths.push_back("line_color"); - res &= check_numeric("line_color",params, info, false); - res &= check_numeric("line_thickness",params, info, false); - res &= check_string("draw_mesh",params, info, false); + detail::dray_color_table_schema(param_schema["properties/color_table"]); + + param_schema["required"].append() = "field"; - ignore_paths.push_back("camera"); - ignore_paths.push_back("color_table"); - - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if(params.has_path("color_table")) + // --- check image name --- { - surprises += detail::dray_color_table_surprises(params["color_table"]); - } + conduit::Node &db_name_schema = param_schema["oneOf"].append(); + db_name_schema["type"] = "object"; + db_name_schema["required"].append() = "camera"; + db_name_schema["constraints/forbid"].append() = "image_prefix"; - if(surprises != "") + conduit::Node &camera_schema_1 = db_name_schema["properties/camera"].append(); + camera_schema_1["type"] = "object"; + camera_schema_1["required"].append() = "db_name"; + } { - res = false; - info["errors"].append() = surprises; + conduit::Node &image_prefix_schema = param_schema["oneOf"].append(); + image_prefix_schema["type"] = "object"; + image_prefix_schema["required"].append() = "image_prefix"; + + conduit::Node &camera_schema_2 = image_prefix_schema["properties/camera"].append(); + camera_schema_2["type"] = "object"; + camera_schema_2["constraints/forbid"].append() = "db_name"; } - return res; } //----------------------------------------------------------------------------- @@ -1453,72 +1398,58 @@ DRay3Slice::declare_interface(Node &i) i["type_name"] = "dray_3slice"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} - -//----------------------------------------------------------------------------- -bool -DRay3Slice::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - - bool res = true; - - res &= check_string("field",params, info, true); - res &= detail::check_image_names(params, info); - res &= check_numeric("min_value",params, info, false); - res &= check_numeric("max_value",params, info, false); - res &= check_numeric("image_width",params, info, false); - res &= check_numeric("image_height",params, info, false); - res &= check_string("log_scale",params, info, false); - res &= check_string("annotations",params, info, false); - - std::vector valid_paths; - std::vector ignore_paths; - valid_paths.push_back("field"); - valid_paths.push_back("image_prefix"); - valid_paths.push_back("min_value"); - valid_paths.push_back("max_value"); - valid_paths.push_back("annotations"); - valid_paths.push_back("image_width"); - valid_paths.push_back("image_height"); - valid_paths.push_back("log_scale"); - - // filter knobs - res &= check_numeric("x_offset",params, info, false); - res &= check_numeric("y_offset",params, info, false); - res &= check_numeric("z_offset",params, info, false); - - res &= check_numeric("sweep/count",params, info, false); - res &= check_string("sweep/axis",params, info, false); - - valid_paths.push_back("x_offset"); - valid_paths.push_back("y_offset"); - valid_paths.push_back("z_offset"); - - valid_paths.push_back("sweep/count"); - valid_paths.push_back("sweep/axis"); - - ignore_paths.push_back("camera"); - ignore_paths.push_back("color_table"); - - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if(params.has_path("color_table")) - { - surprises += detail::dray_color_table_surprises(params["color_table"]); + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + + string_schema(param_schema["properties/field"]); + string_schema(param_schema["properties/image_prefix"]); + number_schema(param_schema["properties/min_value"]); + number_schema(param_schema["properties/max_value"]); + number_schema(param_schema["properties/image_width"]); + number_schema(param_schema["properties/image_height"]); + string_schema(param_schema["properties/log_scale"]); + string_schema(param_schema["properties/annotations"]); + number_schema(param_schema["properties/x_offset"]); + number_schema(param_schema["properties/y_offset"]); + number_schema(param_schema["properties/z_offset"]); + ignore_schema(param_schema["properties/camera"]); + + detail::dray_color_table_schema(param_schema["properties/color_table"]); + + // --- sweep --- + conduit::Node &sweep_schema = param_schema["properties/sweep"]; + sweep_schema["type"] = "object"; + sweep_schema["additionalProperties"] = false; + number_schema(sweep_schema["properties/count"]); + string_schema(sweep_schema["properties/axis"]); + + param_schema["required"].append() = "field"; + + // --- check image name --- + { + conduit::Node &db_name_schema = param_schema["oneOf"].append(); + db_name_schema["type"] = "object"; + db_name_schema["required"].append() = "camera"; + db_name_schema["constraints/forbid"].append() = "image_prefix"; + + conduit::Node &camera_schema_1 = db_name_schema["properties/camera"].append(); + camera_schema_1["type"] = "object"; + camera_schema_1["required"].append() = "db_name"; + } + { + conduit::Node &image_prefix_schema = param_schema["oneOf"].append(); + image_prefix_schema["type"] = "object"; + image_prefix_schema["required"].append() = "image_prefix"; + + conduit::Node &camera_schema_2 = image_prefix_schema["properties/camera"].append(); + camera_schema_2["type"] = "object"; + camera_schema_2["constraints/forbid"].append() = "db_name"; } - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } - return res; } - //----------------------------------------------------------------------------- void DRay3Slice::execute() @@ -1848,67 +1779,49 @@ DRayVolume::declare_interface(Node &i) i["type_name"] = "dray_volume"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} - -//----------------------------------------------------------------------------- -bool -DRayVolume::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - - bool res = true; - - res &= check_string("field",params, info, true); - res &= detail::check_image_names(params, info); - res &= check_numeric("min_value",params, info, false); - res &= check_numeric("max_value",params, info, false); - res &= check_numeric("image_width",params, info, false); - res &= check_numeric("image_height",params, info, false); - res &= check_string("log_scale",params, info, false); - res &= check_string("annotations",params, info, false); - - std::vector valid_paths; - std::vector ignore_paths; - - valid_paths.push_back("field"); - valid_paths.push_back("image_prefix"); - valid_paths.push_back("min_value"); - valid_paths.push_back("max_value"); - valid_paths.push_back("image_width"); - valid_paths.push_back("image_height"); - valid_paths.push_back("log_scale"); - valid_paths.push_back("annotations"); - - // filter knobs - res &= check_numeric("samples",params, info, false); - res &= check_string("use_lighing",params, info, false); - - valid_paths.push_back("samples"); - valid_paths.push_back("use_lighting"); - - ignore_paths.push_back("camera"); - ignore_paths.push_back("color_table"); - ignore_paths.push_back("load_balancing"); - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if(params.has_path("color_table")) - { - surprises += detail::dray_color_table_surprises(params["color_table"]); - } - - if(params.has_path("load_balancing")) - { - surprises += detail::dray_load_balance_surprises(params["load_balancing"]); - } - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + + string_schema(param_schema["properties/field"]); + string_schema(param_schema["properties/image_prefix"]); + number_schema(param_schema["properties/min_value"]); + number_schema(param_schema["properties/max_value"]); + number_schema(param_schema["properties/image_width"]); + number_schema(param_schema["properties/image_height"]); + string_schema(param_schema["properties/log_scale"]); + string_schema(param_schema["properties/annotations"]); + number_schema(param_schema["properties/samples"]); + bool_schema(param_schema["properties/use_lighing"]); + ignore_schema(param_schema["properties/camera"]); + + detail::dray_color_table_schema(param_schema["properties/color_table"]); + detail::dray_load_balance_schema(param_schema["properties/load_balancing"]); + + param_schema["required"].append() = "field"; + + // --- check image name --- + { + conduit::Node &db_name_schema = param_schema["oneOf"].append(); + db_name_schema["type"] = "object"; + db_name_schema["required"].append() = "camera"; + db_name_schema["constraints/forbid"].append() = "image_prefix"; + + conduit::Node &camera_schema_1 = db_name_schema["properties/camera"].append(); + camera_schema_1["type"] = "object"; + camera_schema_1["required"].append() = "db_name"; + } + { + conduit::Node &image_prefix_schema = param_schema["oneOf"].append(); + image_prefix_schema["type"] = "object"; + image_prefix_schema["required"].append() = "image_prefix"; + + conduit::Node &camera_schema_2 = image_prefix_schema["properties/camera"].append(); + camera_schema_2["type"] = "object"; + camera_schema_2["constraints/forbid"].append() = "db_name"; } - return res; } //----------------------------------------------------------------------------- @@ -2062,43 +1975,31 @@ DRayReflect::declare_interface(Node &i) i["type_name"] = "dray_reflect"; i["port_names"].append() = "in"; i["output_port"] = "true"; -} - -//----------------------------------------------------------------------------- -bool -DRayReflect::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - - bool res = true; - - res &= check_numeric("point/x",params, info, true); - res &= check_numeric("point/y",params, info, true); - res &= check_numeric("point/z",params, info, false); - res &= check_numeric("normal/x",params, info, true); - res &= check_numeric("normal/y",params, info, true); - res &= check_numeric("normal/z",params, info, false); - - std::vector valid_paths; - std::vector ignore_paths; - - valid_paths.push_back("point/x"); - valid_paths.push_back("point/y"); - valid_paths.push_back("point/z"); - valid_paths.push_back("normal/x"); - valid_paths.push_back("normal/y"); - valid_paths.push_back("normal/z"); - - std::string surprises = surprise_check(valid_paths, params); - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } - return res; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + + // --- point --- + conduit::Node &point_schema = param_schema["properties/point"]; + point_schema["type"] = "object"; + point_schema["additionalProperties"] = false; + number_schema(point_schema["properties/x"]); + number_schema(point_schema["properties/y"]); + number_schema(point_schema["properties/z"]); + point_schema["required"].append() = "x"; + point_schema["required"].append() = "y"; + + // --- normal --- + conduit::Node &normal_schema = param_schema["properties/normal"]; + normal_schema["type"] = "object"; + normal_schema["additionalProperties"] = false; + number_schema(normal_schema["properties/x"]); + number_schema(normal_schema["properties/y"]); + number_schema(normal_schema["properties/z"]); + normal_schema["required"].append() = "x"; + normal_schema["required"].append() = "y"; } //----------------------------------------------------------------------------- @@ -2174,39 +2075,17 @@ DRayProject2d::declare_interface(Node &i) i["type_name"] = "dray_project_2d"; i["port_names"].append() = "in"; i["output_port"] = "true"; -} - -//----------------------------------------------------------------------------- -bool -DRayProject2d::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = true; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - res &= check_numeric("image_width",params, info, false); - res &= check_numeric("image_height",params, info, false); - - std::vector valid_paths; - std::vector ignore_paths; - - valid_paths.push_back("image_width"); - valid_paths.push_back("image_height"); - valid_paths.push_back("fields"); - - ignore_paths.push_back("camera"); - ignore_paths.push_back("plane"); - ignore_paths.push_back("fields"); - - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } - return res; + ignore_schema(param_schema["properties/fields"]); + number_schema(param_schema["properties/image_width"]); + number_schema(param_schema["properties/image_height"]); + ignore_schema(param_schema["properties/camera"]); + ignore_schema(param_schema["properties/plane"]); } //----------------------------------------------------------------------------- @@ -2362,53 +2241,23 @@ DRayProjectColors2d::declare_interface(Node &i) i["type_name"] = "dray_project_colors_2d"; i["port_names"].append() = "in"; i["output_port"] = "true"; -} - -//----------------------------------------------------------------------------- -bool -DRayProjectColors2d::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - - bool res = true; - - res &= check_numeric("image_width",params, info, false); - res &= check_numeric("image_height",params, info, false); - res &= check_string("field",params, info, true); - - res &= check_numeric("min_value",params, info, false); - res &= check_numeric("max_value",params, info, false); - res &= check_numeric("image_width",params, info, false); - res &= check_numeric("image_height",params, info, false); - res &= check_string("log_scale",params, info, false); - - std::vector valid_paths; - std::vector ignore_paths; - - valid_paths.push_back("image_width"); - valid_paths.push_back("image_height"); - valid_paths.push_back("min_value"); - valid_paths.push_back("max_value"); - valid_paths.push_back("log_scale"); - valid_paths.push_back("field"); - ignore_paths.push_back("camera"); - ignore_paths.push_back("color_table"); - - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if(params.has_path("color_table")) - { - surprises += detail::dray_color_table_surprises(params["color_table"]); - } - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } - return res; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + + string_schema(param_schema["properties/field"]); + number_schema(param_schema["properties/min_value"]); + number_schema(param_schema["properties/max_value"]); + number_schema(param_schema["properties/image_width"]); + number_schema(param_schema["properties/image_height"]); + string_schema(param_schema["properties/log_scale"]); + ignore_schema(param_schema["properties/camera"]); + + detail::dray_color_table_schema(param_schema["properties/color_table"]); + + param_schema["required"].append() = "field"; } //----------------------------------------------------------------------------- @@ -2505,33 +2354,19 @@ DRayVectorComponent::declare_interface(Node &i) i["type_name"] = "dray_vector_component"; i["port_names"].append() = "in"; i["output_port"] = "true"; -} -//----------------------------------------------------------------------------- -bool -DRayVectorComponent::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - - bool res = check_string("field",params, info, true); - res &= check_numeric("component",params, info, true); - res &= check_string("output_name",params, info, true); - - std::vector valid_paths; - valid_paths.push_back("field"); - valid_paths.push_back("component"); - valid_paths.push_back("output_name"); + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - std::string surprises = surprise_check(valid_paths, params); - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } + string_schema(param_schema["properties/field"]); + number_schema(param_schema["properties/component"]); + string_schema(param_schema["properties/output_name"]); - return res; + param_schema["required"].append() = "field"; + param_schema["required"].append() = "component"; + param_schema["required"].append() = "output_name"; } //----------------------------------------------------------------------------- diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.hpp index 316bf8aca..3c12c30cf 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_dray_filters.hpp @@ -50,8 +50,6 @@ class ASCENT_API DRayPseudocolor : public ::flow::Filter virtual ~DRayPseudocolor(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -63,8 +61,6 @@ class ASCENT_API DRay3Slice : public ::flow::Filter virtual ~DRay3Slice(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -76,8 +72,6 @@ class ASCENT_API DRayVolume : public ::flow::Filter virtual ~DRayVolume(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -88,8 +82,6 @@ class ASCENT_API DRayProject2d: public ::flow::Filter DRayProject2d(); virtual ~DRayProject2d(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -100,8 +92,6 @@ class ASCENT_API DRayProjectColors2d: public ::flow::Filter DRayProjectColors2d(); virtual ~DRayProjectColors2d(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -113,8 +103,6 @@ class ASCENT_API DRayReflect : public ::flow::Filter virtual ~DRayReflect(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -126,8 +114,6 @@ class ASCENT_API DRayVectorComponent : public ::flow::Filter virtual ~DRayVectorComponent(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_genten_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_genten_filters.cpp index 8a54e210d..60d72dedc 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_genten_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_genten_filters.cpp @@ -235,18 +235,6 @@ Learn::declare_interface(Node &i) i["output_port"] = "false"; } - -//----------------------------------------------------------------------------- -bool -Learn::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - // TODO: Anything goes right now :-) - bool res = true; - return res; -} - //----------------------------------------------------------------------------- void Learn::execute() diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_genten_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_genten_filters.hpp index f73ccdb73..1df89f2c4 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_genten_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_genten_filters.hpp @@ -52,8 +52,6 @@ class ASCENT_API Learn : public ::flow::Filter ~Learn(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_hola_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_hola_filters.cpp index 88f9b30f3..e5100ba6b 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_hola_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_hola_filters.cpp @@ -29,6 +29,7 @@ //----------------------------------------------------------------------------- #include #include +#include #include #include @@ -76,32 +77,19 @@ HolaMPIExtract::declare_interface(Node &i) i["type_name"] = "hola_mpi"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} -//----------------------------------------------------------------------------- -bool -HolaMPIExtract::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = true; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - if(! params.has_child("mpi_comm") || - ! params["mpi_comm"].dtype().is_integer() ) - { - info["errors"].append() = "Missing required integer parameter 'mpi_comm'"; - } + integer_schema(param_schema["properties/mpi_comm"]); + integer_schema(param_schema["properties/rank_split"]); - if(! params.has_child("rank_split") || - ! params["rank_split"].dtype().is_integer() ) - { - info["errors"].append() = "Missing required integer parameter 'rank_split'"; - } - - return res; + param_schema["required"].append() = "mpi_comm"; + param_schema["required"].append() = "rank_split"; } - //----------------------------------------------------------------------------- void HolaMPIExtract::execute() diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_hola_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_hola_filters.hpp index 8129bd0a9..dc6410bcd 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_hola_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_hola_filters.hpp @@ -51,8 +51,6 @@ class ASCENT_API HolaMPIExtract: public ::flow::Filter ~HolaMPIExtract(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_htg_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_htg_filters.cpp index 5f9e56804..6548d3cf6 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_htg_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_htg_filters.cpp @@ -75,58 +75,6 @@ namespace detail //----------------------------------------------------------------------------- // helper used by io save -//----------------------------------------------------------------------------- -bool -verify_htg_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - bool res = true; - - if( !params.has_child("path") ) - { - info["errors"].append() = "missing required entry 'path'"; - res = false; - } - else if(!params["path"].dtype().is_string()) - { - info["errors"].append() = "'path' must be a string"; - res = false; - } - else if(params["path"].as_string().empty()) - { - info["errors"].append() = "'path' is an empty string"; - res = false; - } - - if( !params.has_child("blank_value") ) - { - info["errors"].append() = "missing required entry 'blank_value'"; - res = false; - } - else if(!params["blank_value"].dtype().is_number()) - { - info["errors"].append() = "'blank_value' must be a number"; - res = false; - } - - std::vector valid_paths; - std::vector ignore_paths; - valid_paths.push_back("path"); - valid_paths.push_back("fields"); - valid_paths.push_back("blank_value"); - ignore_paths.push_back("fields"); - - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if(surprises != "") - { - info["errors"].append() = surprises; - res = false; - } - - return res; -} - //----------------------------------------------------------------------------- float htg_create(const float *var_in, float *var_out, @@ -659,14 +607,18 @@ HTGIOSave::declare_interface(Node &i) i["type_name"] = "htg_io_save"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} -//----------------------------------------------------------------------------- -bool -HTGIOSave::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - return verify_htg_params(params,info); + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + + string_schema(param_schema["properties/path"], 1); + number_schema(param_schema["properties/blank_value"]); + ignore_schema(param_schema["properties/fields"]); + + param_schema["required"].append() = "path"; + param_schema["required"].append() = "blank_value"; } //----------------------------------------------------------------------------- diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_htg_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_htg_filters.hpp index 988de1292..f60b4efc6 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_htg_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_htg_filters.hpp @@ -51,8 +51,6 @@ class ASCENT_API HTGIOSave : public ::flow::Filter ~HTGIOSave(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_param_check.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_param_check.cpp index f84190b5b..7677f6521 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_param_check.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_param_check.cpp @@ -86,13 +86,49 @@ void ascent_register_flow_schema_hooks() flow::schema::register_format_checker("expression", &is_valid_expression); } -conduit::Node &string_schema(conduit::Node &schema_node) +//----------------------------------------------------------------------------- + +conduit::Node &string_schema(conduit::Node &schema_node, + size_t minLength, + size_t maxLength) { schema_node.reset(); schema_node["type"] = "string"; + + if(minLength != 0) + { + schema_node["minLength"] = minLength; + } + + if(maxLength != std::numeric_limits::max()) + { + schema_node["maxLength"] = maxLength; + } + + return schema_node; +} + +//----------------------------------------------------------------------------- + +conduit::Node &string_enum_schema(conduit::Node &schema_node, const std::vector &options) +{ + string_schema(schema_node); + + for (const auto& value: options) + { + schema_node["enum"].append() = value; + } + return schema_node; } +conduit::Node &bool_schema(conduit::Node &schema_node) +{ + return string_enum_schema(schema_node, {"true", "false"}); +} + +//----------------------------------------------------------------------------- + conduit::Node &expression_schema(conduit::Node &schema_node) { string_schema(schema_node); @@ -100,21 +136,90 @@ conduit::Node &expression_schema(conduit::Node &schema_node) return schema_node; } -conduit::Node &number_schema(conduit::Node &schema_node, bool supports_expressions) +//----------------------------------------------------------------------------- + +conduit::Node &number_schema(conduit::Node &schema_node, + const bool supports_expressions, + const int minimum, + const int maximum, + const int exclusiveMinimum, + const int exclusiveMaximum) { schema_node.reset(); + if (supports_expressions) { - number_schema(schema_node["oneOf"].append()); + number_schema(schema_node["oneOf"].append(), false, minimum, maximum, exclusiveMinimum, exclusiveMaximum); expression_schema(schema_node["oneOf"].append()); } else { schema_node["type"] = "number"; + + if(exclusiveMinimum != std::numeric_limits::lowest()) + { + schema_node["exclusiveMinimum"] = exclusiveMinimum; + } + else if(minimum != std::numeric_limits::lowest()) + { + schema_node["minimum"] = minimum; + } + + if(exclusiveMaximum != std::numeric_limits::max()) + { + schema_node["exclusiveMaximum"] = exclusiveMaximum; + } + else if(maximum != std::numeric_limits::max()) + { + schema_node["maximum"] = maximum; + } + } + + return schema_node; +} + +conduit::Node &integer_schema(conduit::Node &schema_node, + const bool supports_expressions, + const int minimum, + const int maximum, + const int exclusiveMinimum, + const int exclusiveMaximum) +{ + schema_node.reset(); + + if (supports_expressions) + { + integer_schema(schema_node["oneOf"].append(), false, minimum, maximum, exclusiveMinimum, exclusiveMaximum); + expression_schema(schema_node["oneOf"].append()); + } + else + { + schema_node["type"] = "integer"; + + if(exclusiveMinimum != std::numeric_limits::lowest()) + { + schema_node["exclusiveMinimum"] = exclusiveMinimum; + } + else if(minimum != std::numeric_limits::lowest()) + { + schema_node["minimum"] = minimum; + } + + if(exclusiveMaximum != std::numeric_limits::max()) + { + schema_node["exclusiveMaximum"] = exclusiveMaximum; + } + else if(maximum != std::numeric_limits::max()) + { + schema_node["maximum"] = maximum; + } } + return schema_node; } +//----------------------------------------------------------------------------- + conduit::Node &vec3_schema(conduit::Node &schema_node, const std::string var1, const std::string var2, @@ -159,15 +264,15 @@ conduit::Node &vec3_schema_anyOf(conduit::Node &schema_node, conduit::Node &var1_required = schema_node["anyOf"].append(); var1_required["type"] = "object"; - var1_required["required"] = var1; + var1_required["required"].append() = var1; conduit::Node &var2_required = schema_node["anyOf"].append(); var2_required["type"] = "object"; - var2_required["required"] = var2; + var2_required["required"].append() = var2; conduit::Node &var3_required = schema_node["anyOf"].append(); var3_required["type"] = "object"; - var3_required["required"] = var3; + var3_required["required"].append() = var3; return schema_node; } @@ -177,11 +282,27 @@ conduit::Node &vec3_schema_anyOf(conduit::Node &schema_node, bool supports_expre return vec3_schema_anyOf(schema_node, "x", "y", "z", supports_expressions); } -conduit::Node &array_schema(conduit::Node &schema_node, const conduit::Node &item_schema) +//----------------------------------------------------------------------------- + +conduit::Node &array_schema(conduit::Node &schema_node, + const conduit::Node &item_schema, + const std::size_t minItems, + const std::size_t maxItems) { schema_node.reset(); schema_node["type"] = "array"; + + if(minItems != 0) + { + schema_node["minItems"] = minItems; + } + + if(maxItems != std::numeric_limits::max()) + { + schema_node["maxItems"] = maxItems; + } + if (!item_schema.dtype().is_empty()) { schema_node["items"].set(item_schema); @@ -190,12 +311,7 @@ conduit::Node &array_schema(conduit::Node &schema_node, const conduit::Node &ite return schema_node; } -conduit::Node &array_schema(conduit::Node &schema_node) -{ - schema_node.reset(); - schema_node["type"] = "array"; - return schema_node; -} +//----------------------------------------------------------------------------- conduit::Node &ignore_schema(conduit::Node &schema_node) { diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_param_check.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_param_check.hpp index ce4da0e77..a4d03e688 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_param_check.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_param_check.hpp @@ -45,33 +45,50 @@ bool ASCENT_API is_valid_expression(const std::string &expr, std::string &err_ms void ASCENT_API ascent_register_flow_schema_hooks(); -conduit::Node ASCENT_API &string_schema(conduit::Node &schema_node); +conduit::Node ASCENT_API &string_schema(conduit::Node &schema_node, + const std::size_t minLength = 0, + const std::size_t maxLength = std::numeric_limits::max()); + +conduit::Node ASCENT_API &string_enum_schema(conduit::Node &schema_node, const std::vector &options); + +conduit::Node ASCENT_API &bool_schema(conduit::Node &schema_node); conduit::Node ASCENT_API &number_schema(conduit::Node &schema_node, - bool supports_expressions = false); + const bool supports_expressions = false, + const int minimum = std::numeric_limits::lowest(), + const int maximum = std::numeric_limits::max(), + const int exclusiveMinimum = std::numeric_limits::lowest(), + const int exclusiveMaximum = std::numeric_limits::max()); + +conduit::Node ASCENT_API &integer_schema(conduit::Node &schema_node, + const bool supports_expressions = false, + const int minimum = std::numeric_limits::lowest(), + const int maximum = std::numeric_limits::max(), + const int exclusiveMinimum = std::numeric_limits::lowest(), + const int exclusiveMaximum = std::numeric_limits::max()); conduit::Node ASCENT_API &vec3_schema(conduit::Node &schema_node, - bool supports_expressions = false); + const bool supports_expressions = false); conduit::Node ASCENT_API &vec3_schema(conduit::Node &schema_node, const std::string var1, const std::string var2, const std::string var3, - bool supports_expressions = false); + const bool supports_expressions = false); conduit::Node ASCENT_API &vec3_schema_anyOf(conduit::Node &schema_node, - bool supports_expressions = false); + const bool supports_expressions = false); conduit::Node ASCENT_API &vec3_schema_anyOf(conduit::Node &schema_node, const std::string var1, const std::string var2, const std::string var3, - bool supports_expressions = false); - -conduit::Node ASCENT_API &array_schema(conduit::Node &schema_node); + const bool supports_expressions = false); conduit::Node ASCENT_API &array_schema(conduit::Node &schema_node, - const conduit::Node &item_schema); + const conduit::Node &item_schema = conduit::Node(), + const std::size_t minItems = 0, + const std::size_t maxItems = std::numeric_limits::max()); conduit::Node ASCENT_API &ignore_schema(conduit::Node &schema_node); diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_query_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_query_filters.cpp index 223162a25..6bea66538 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_query_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_query_filters.cpp @@ -81,25 +81,19 @@ BasicQuery::declare_interface(Node &i) // adding an output port to chain queries together // so they execute in order of declaration i["output_port"] = "true"; -} -//----------------------------------------------------------------------------- -bool -BasicQuery::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = check_string("expression",params, info, true); - res &= check_string("name",params, info, true); + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - std::vector valid_paths; - valid_paths.push_back("expression"); - valid_paths.push_back("name"); + string_schema(param_schema["properties/expression"]); + string_schema(param_schema["properties/name"]); - return res; + param_schema["required"].append() = "expression"; + param_schema["required"].append() = "name"; } - //----------------------------------------------------------------------------- void BasicQuery::execute() @@ -152,25 +146,19 @@ FilterQuery::declare_interface(Node &i) i["type_name"] = "expression"; i["port_names"].append() = "in"; i["output_port"] = "true"; -} -//----------------------------------------------------------------------------- -bool -FilterQuery::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = check_string("expression",params, info, true); - res &= check_string("name",params, info, true); + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - std::vector valid_paths; - valid_paths.push_back("expression"); - valid_paths.push_back("name"); + string_schema(param_schema["properties/expression"]); + string_schema(param_schema["properties/name"]); - return res; + param_schema["required"].append() = "expression"; + param_schema["required"].append() = "name"; } - //----------------------------------------------------------------------------- void FilterQuery::execute() diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_query_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_query_filters.hpp index eed65ad10..dcdbfec40 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_query_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_query_filters.hpp @@ -51,8 +51,6 @@ class ASCENT_API BasicQuery : public ::flow::Filter ~BasicQuery(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -63,8 +61,6 @@ class ASCENT_API FilterQuery : public ::flow::Filter ~FilterQuery(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.cpp index 39e2281df..7cd342779 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.cpp @@ -421,74 +421,21 @@ post_filter_check_for_data(const conduit::Node &output) //----------------------------------------------------------------------------- // helper shared by io save and load //----------------------------------------------------------------------------- -bool -verify_io_params(const conduit::Node ¶ms, - conduit::Node &info) +void io_param_schema(conduit::Node ¶m_schema) { - bool res = true; + // ----------- Define Param Schema ----------- + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - if( !params.has_child("path") ) - { - info["errors"].append() = "missing required entry 'path'"; - res = false; - } - else if(!params["path"].dtype().is_string()) - { - info["errors"].append() = "'path' must be a string"; - res = false; - } - else if(params["path"].as_string().empty()) - { - info["errors"].append() = "'path' is an empty string"; - res = false; - } - - if( params.has_child("protocol") ) - { - if(!params["protocol"].dtype().is_string()) - { - info["errors"].append() = "optional entry 'protocol' must be a string"; - res = false; - } - else if(params["protocol"].as_string().empty()) - { - info["errors"].append() = "'protocol' is an empty string"; - res = false; - } - else - { - info["info"].append() = "includes 'protocol'"; - } - } - - if( params.has_child("num_files") ) - { - if(!params["num_files"].dtype().is_integer()) - { - info["errors"].append() = "optional entry 'num_files' must be an integer"; - res = false; - } - else - { - info["info"].append() = "includes 'num_files'"; - } - } - - if( params.has_child("refinement_level") ) - { - if(!params["refinement_level"].dtype().is_integer()) - { - info["errors"].append() = "optional entry 'refinement_level' must be an integer"; - res = false; - } - else - { - info["info"].append() = "includes 'refinement_level'"; - } - } + string_schema(param_schema["properties/path"], 1); + string_schema(param_schema["properties/protocol"], 1); + ignore_schema(param_schema["properties/topologies"]); + ignore_schema(param_schema["properties/fields"]); + integer_schema(param_schema["properties/num_files"]); + integer_schema(param_schema["properties/refinement_level"]); #if defined(ASCENT_HDF5_ENABLED) - if( params.has_child("hdf5_options") ) + // --- HDF5 --- { // // HDF5 OPTIONS Example: @@ -504,84 +451,32 @@ verify_io_params(const conduit::Node ¶ms, // method: "gzip" // level: 5 - const Node ¶ms_hdf5_opts = params["hdf5_options"]; - - res &= check_object("compact_storage", - params_hdf5_opts, - info, - false); - - res &= check_bool("compact_storage/enabled", - params_hdf5_opts, - info, - false); - - res &= check_numeric("compact_storage/threshold", - params_hdf5_opts, - info, - false); - - res &= check_object("chunking", - params_hdf5_opts, - info, - false); - - res &= check_bool("chunking/enabled", - params_hdf5_opts, - info, - false); - - - res &= check_numeric("chunking/threshold", - params_hdf5_opts, - info, - false); - - res &= check_numeric("chunking/chunk_size", - params_hdf5_opts, - info, - false); - - res &= check_object("chunking/compression", - params_hdf5_opts, - info, - false); - - res &= check_string("chunking/compression/method", - params_hdf5_opts, - info, - false); - - res &= check_numeric("chunking/compression/level", - params_hdf5_opts, - info, - false); + conduit::Node &hdf5_schema = param_schema["properties/hdf5_options"]; + hdf5_schema["type"] = "object"; + hdf5_schema["additionalProperties"] = false; + + conduit::Node &hdf5_compact_storage_schema = hdf5_schema["properties/compact_storage"]; + hdf5_compact_storage_schema["type"] = "object"; + hdf5_compact_storage_schema["additionalProperties"] = false; + bool_schema(hdf5_compact_storage_schema["properties/enabled"]); + number_schema(hdf5_compact_storage_schema["properties/threshold"]); + + conduit::Node &hdf5_chunking_schema = hdf5_schema["properties/chunking"]; + hdf5_chunking_schema["type"] = "object"; + hdf5_chunking_schema["additionalProperties"] = false; + bool_schema(hdf5_chunking_schema["properties/enabled"]); + number_schema(hdf5_chunking_schema["properties/threshold"]); + number_schema(hdf5_chunking_schema["properties/chunk_size"]); + + conduit::Node &hdf5_compression_schema = hdf5_chunking_schema["properties/compression"]; + hdf5_compression_schema["type"] = "object"; + hdf5_compression_schema["additionalProperties"] = false; + string_schema(hdf5_compression_schema["properties/method"]); + number_schema(hdf5_compression_schema["properties/level"]); } #endif - std::vector valid_paths; - std::vector ignore_paths; - valid_paths.push_back("path"); - valid_paths.push_back("protocol"); - valid_paths.push_back("topologies"); - valid_paths.push_back("fields"); - valid_paths.push_back("num_files"); - valid_paths.push_back("refinement_level"); - ignore_paths.push_back("fields"); - ignore_paths.push_back("topologies"); -#if defined(ASCENT_HDF5_ENABLED) - ignore_paths.push_back("hdf5_options"); -#endif - - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } - - return res; + param_schema["required"].append() = "path"; } @@ -709,17 +604,11 @@ RelayIOSave::declare_interface(Node &i) i["type_name"] = "relay_io_save"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} -//----------------------------------------------------------------------------- -bool -RelayIOSave::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - return verify_io_params(params,info); + // ----------- Define Param Schema ----------- + io_param_schema(i["param_schema"]); } - //----------------------------------------------------------------------------- void RelayIOSave::execute() @@ -1098,17 +987,11 @@ RelayIOLoad::declare_interface(Node &i) i["type_name"] = "relay_io_load"; i["port_names"] = DataType::empty(); i["output_port"] = "true"; -} -//----------------------------------------------------------------------------- -bool -RelayIOLoad::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - return verify_io_params(params,info); + // ----------- Define Param Schema ----------- + io_param_schema(i["param_schema"]); } - //----------------------------------------------------------------------------- void RelayIOLoad::execute() @@ -1156,40 +1039,19 @@ BlueprintFlatten::declare_interface(Node &i) i["type_name"] = "false"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} - -//----------------------------------------------------------------------------- -bool -BlueprintFlatten::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = true; - if(! params.has_child("path") || - ! params["path"].dtype().is_string() ) - { - info["errors"].append() = "Missing required string parameter 'path'"; - } + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - std::vector valid_paths; - valid_paths.push_back("path"); - valid_paths.push_back("protocol"); - valid_paths.push_back("fields"); + string_schema(param_schema["properties/path"]); + string_schema(param_schema["properties/protocol"]); + array_schema(string_schema(param_schema["properties/fields"])); - std::string surprises = surprise_check(valid_paths, params); - - if(surprises != "") - { - res = false; - info["error"].append() = surprises; - } - - return res; - //return verify_io_params(params,info); + param_schema["required"].append() = "path"; } - //----------------------------------------------------------------------------- void BlueprintFlatten::execute() diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.hpp index c042d76a0..0b7bdeb2c 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.hpp @@ -58,8 +58,6 @@ class ASCENT_API RelayIOSave : public ::flow::Filter ~RelayIOSave(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -71,8 +69,6 @@ class ASCENT_API RelayIOLoad : public ::flow::Filter ~RelayIOLoad(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; //----------------------------------------------------------------------------- @@ -83,8 +79,6 @@ class ASCENT_API BlueprintFlatten : public ::flow::Filter ~BlueprintFlatten(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rendering_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rendering_filters.cpp index 6abbbb4cd..ae4b0c0e3 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rendering_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rendering_filters.cpp @@ -87,192 +87,46 @@ namespace filters //----------------------------------------------------------------------------- namespace detail { -std::string -check_color_table_surprises(const conduit::Node &color_table) -{ - std::string surprises; - - std::vector valid_paths; - valid_paths.push_back("name"); - valid_paths.push_back("reverse"); - valid_paths.push_back("annotation"); - valid_paths.push_back("discrete"); - - std::vector ignore_paths; - ignore_paths.push_back("control_points"); - - surprises += surprise_check(valid_paths, ignore_paths, color_table); - if(color_table.has_path("control_points")) - { - const Node &control_points_node = color_table.fetch("control_points"); - - if (control_points_node.dtype().is_list()) - { - // Valid path options for the expanded control points input format - std::vector c_valid_paths; - c_valid_paths.push_back("type"); - c_valid_paths.push_back("alpha"); - c_valid_paths.push_back("color"); - c_valid_paths.push_back("position"); - - const int num_points = control_points_node.number_of_children(); - for(int i = 0; i < num_points; ++i) - { - const conduit::Node &point = control_points_node.child(i); - surprises += surprise_check(c_valid_paths, point); - } - } - else if (control_points_node.dtype().is_object()) - { - // Valid path options for the compressed control points input format - std::vector c_valid_paths; - c_valid_paths.push_back("r"); - c_valid_paths.push_back("g"); - c_valid_paths.push_back("b"); - c_valid_paths.push_back("a"); - c_valid_paths.push_back("position"); - - - surprises += surprise_check(c_valid_paths, control_points_node); - } - } - - return surprises; -} -std::string -check_renders_surprises(const conduit::Node &renders_node) -{ - std::string surprises; - const int num_renders = renders_node.number_of_children(); - // render paths - std::vector r_valid_paths; - r_valid_paths.push_back("camera/2d"); - r_valid_paths.push_back("image_name"); - r_valid_paths.push_back("image_prefix"); - r_valid_paths.push_back("image_width"); - r_valid_paths.push_back("image_height"); - r_valid_paths.push_back("scene_bounds"); - r_valid_paths.push_back("type"); - r_valid_paths.push_back("phi"); - r_valid_paths.push_back("phi_range"); - r_valid_paths.push_back("dphi"); - r_valid_paths.push_back("phi_num_angles"); - r_valid_paths.push_back("phi_angles"); - r_valid_paths.push_back("theta"); - r_valid_paths.push_back("theta_range"); - r_valid_paths.push_back("dtheta"); - r_valid_paths.push_back("theta_num_angles"); - r_valid_paths.push_back("theta_angles"); - r_valid_paths.push_back("phi_theta_positions"); - r_valid_paths.push_back("db_name"); - r_valid_paths.push_back("output_path"); - r_valid_paths.push_back("render_bg"); - r_valid_paths.push_back("annotations"); - r_valid_paths.push_back("world_annotations"); - r_valid_paths.push_back("screen_annotations"); - r_valid_paths.push_back("axis_scale_x"); - r_valid_paths.push_back("axis_scale_y"); - r_valid_paths.push_back("axis_scale_z"); - r_valid_paths.push_back("fg_color"); - r_valid_paths.push_back("bg_color"); - r_valid_paths.push_back("shading"); - r_valid_paths.push_back("use_original_bounds"); - r_valid_paths.push_back("dataset_bounds"); - r_valid_paths.push_back("auto_camera/metric"); - r_valid_paths.push_back("auto_camera/field"); - r_valid_paths.push_back("auto_camera/samples"); - r_valid_paths.push_back("auto_camera/bins"); - r_valid_paths.push_back("auto_camera/height"); - r_valid_paths.push_back("auto_camera/width"); - r_valid_paths.push_back("color_bar_position"); - r_valid_paths.push_back("tiled_rendering"); - r_valid_paths.push_back("tiled_rendering_type"); - r_valid_paths.push_back("tile_width"); - r_valid_paths.push_back("tile_height"); - - std::vector r_ignore_paths; - r_ignore_paths.push_back("phi_theta_positions"); - r_ignore_paths.push_back("camera"); - - // Valid Ascent input camera format - std::vector c_ascent_valid_paths; - c_ascent_valid_paths.push_back("2d"); - c_ascent_valid_paths.push_back("look_at"); - c_ascent_valid_paths.push_back("position"); - c_ascent_valid_paths.push_back("up"); - c_ascent_valid_paths.push_back("fov"); - c_ascent_valid_paths.push_back("xpan"); - c_ascent_valid_paths.push_back("ypan"); - c_ascent_valid_paths.push_back("zoom"); - c_ascent_valid_paths.push_back("near_plane"); - c_ascent_valid_paths.push_back("far_plane"); - c_ascent_valid_paths.push_back("azimuth"); - c_ascent_valid_paths.push_back("elevation"); - - // Valid Visit input camera format - std::vector c_visit_valid_paths; - c_visit_valid_paths.push_back("windowCoords"); - c_visit_valid_paths.push_back("view_normal"); - c_visit_valid_paths.push_back("focus"); - c_visit_valid_paths.push_back("view_up"); - c_visit_valid_paths.push_back("view_angle"); - c_visit_valid_paths.push_back("parallel_scale"); - c_visit_valid_paths.push_back("near_plane"); - c_visit_valid_paths.push_back("far_plane"); - c_visit_valid_paths.push_back("image_pan"); - c_visit_valid_paths.push_back("image_zoom"); - c_visit_valid_paths.push_back("perspective"); - c_visit_valid_paths.push_back("eye_angle"); - c_visit_valid_paths.push_back("center_of_rotation_set"); - c_visit_valid_paths.push_back("center_of_rotation"); - c_visit_valid_paths.push_back("axis_3d_scale_flag"); - c_visit_valid_paths.push_back("axis_3d_scale"); - c_visit_valid_paths.push_back("shear"); - c_visit_valid_paths.push_back("window_valid"); - - std::vector c_ignore_paths; - - for(int i = 0; i < num_renders; ++i) - { - const conduit::Node &render_node = renders_node.child(i); - surprises += surprise_check(r_valid_paths, r_ignore_paths, render_node); - - if(render_node.has_path("phi_theta_positions")) - { - const conduit::Node &phi_theta_positions = render_node["phi_theta_positions"]; - const int num_positions = phi_theta_positions.number_of_children(); - for(int i = 0; i < num_positions; ++i) - { - const conduit::Node &position = phi_theta_positions.child(i); - std::stringstream ss; - ss << "[" << i << "]"; - if (position.name() != ss.str()) - { - surprises += "Surprise parameter '"; - surprises += position.name(); - surprises += "'\n"; - } - } - } - - if(render_node.has_path("camera")) - { - const conduit::Node &camera_node = render_node["camera"]; - std::string c_ascent_surprises = surprise_check(c_ascent_valid_paths, c_ignore_paths, camera_node); - std::string c_visit_surprises = surprise_check(c_visit_valid_paths, c_ignore_paths, camera_node); - - if(!c_ascent_surprises.empty() && !c_visit_surprises.empty()) - { - surprises += "Cameras must follow either an ascent format or a visit format, not both.\n"; - surprises += "\nAscent camera surpises:\n"; - surprises += c_ascent_surprises; - surprises += "\nVisit camera surprises:\n"; - surprises += c_visit_surprises; - } +void color_table_schema(conduit::Node ¶m_schema) { + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + + string_schema(param_schema["properties/name"]); + bool_schema(param_schema["properties/reverse"]); + string_schema(param_schema["properties/annotation"]); + string_schema(param_schema["properties/discrete"]); + + // --- Control Points --- + { + conduit::Node &control_points_schema = param_schema["properties/control_points"]; + + conduit::Node &cp_compressed_schema = control_points_schema["oneOf"].append(); + cp_compressed_schema["type"] = "object"; + cp_compressed_schema["additionalProperties"] = false; + ignore_schema(cp_compressed_schema["properties/r"]); + ignore_schema(cp_compressed_schema["properties/g"]); + ignore_schema(cp_compressed_schema["properties/b"]); + ignore_schema(cp_compressed_schema["properties/a"]); + ignore_schema(cp_compressed_schema["properties/position"]); + cp_compressed_schema["constraints/forbid"].append() = "type"; + cp_compressed_schema["constraints/forbid"].append() = "alpha"; + cp_compressed_schema["constraints/forbid"].append() = "color"; + + conduit::Node cp_list_item_schema; + cp_list_item_schema["type"] = "object"; + cp_list_item_schema["additionalProperties"] = false; + ignore_schema(cp_list_item_schema["properties/type"]); + ignore_schema(cp_list_item_schema["properties/alpha"]); + ignore_schema(cp_list_item_schema["properties/color"]); + ignore_schema(cp_list_item_schema["properties/position"]); + cp_list_item_schema["constraints/forbid"].append() = "r"; + cp_list_item_schema["constraints/forbid"].append() = "g"; + cp_list_item_schema["constraints/forbid"].append() = "b"; + cp_list_item_schema["constraints/forbid"].append() = "a"; + + array_schema(control_points_schema["oneOf"].append(), cp_list_item_schema); } - } - return surprises; } void viskores_bounds_to_conduit_node(const viskores::Bounds &bounds, @@ -1205,41 +1059,109 @@ CreateRenders::declare_interface(Node &i) i["port_names"].append() = "scene"; i["port_names"].append() = "bounds"; i["output_port"] = "true"; -} - -//----------------------------------------------------------------------------- -bool -CreateRenders::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = check_string("image_name",params, info, false); - res &= check_string("image_prefix",params, info, false); - - std::vector valid_paths; - valid_paths.push_back("image_prefix"); - valid_paths.push_back("image_name"); - std::vector ignore_paths; - ignore_paths.push_back("renders"); - - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - - // parse render surprises - if(params.has_path("renders")) - { - const conduit::Node &renders_node = params["renders"]; - surprises += detail::check_renders_surprises(renders_node); - } - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } - - return res; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + + string_schema(param_schema["properties/image_name"]); + string_schema(param_schema["properties/image_prefix"]); + + // --- render --- + conduit::Node render_schema; + render_schema["type"] = "object"; + render_schema["additionalProperties"] = false; + string_schema(render_schema["properties/image_name"]); + string_schema(render_schema["properties/image_prefix"]); + integer_schema(render_schema["properties/image_width"], true, 0, std::numeric_limits::max(), 0); + integer_schema(render_schema["properties/image_height"], true, 0, std::numeric_limits::max(), 0); + ignore_schema(render_schema["properties/scene_bounds"]); + ignore_schema(render_schema["properties/type"]); + ignore_schema(render_schema["properties/phi"]); + ignore_schema(render_schema["properties/phi_range"]); + ignore_schema(render_schema["properties/dphi"]); + ignore_schema(render_schema["properties/phi_num_angles"]); + ignore_schema(render_schema["properties/phi_angles"]); + ignore_schema(render_schema["properties/theta"]); + ignore_schema(render_schema["properties/theta_range"]); + ignore_schema(render_schema["properties/dtheta"]); + ignore_schema(render_schema["properties/theta_num_angles"]); + ignore_schema(render_schema["properties/theta_angles"]); + ignore_schema(render_schema["properties/phi_theta_positions"]); + ignore_schema(render_schema["properties/db_name"]); + ignore_schema(render_schema["properties/output_path"]); + ignore_schema(render_schema["properties/render_bg"]); + ignore_schema(render_schema["properties/annotations"]); + ignore_schema(render_schema["properties/world_annotations"]); + ignore_schema(render_schema["properties/screen_annotations"]); + ignore_schema(render_schema["properties/axis_scale_x"]); + ignore_schema(render_schema["properties/axis_scale_y"]); + ignore_schema(render_schema["properties/axis_scale_z"]); + ignore_schema(render_schema["properties/fg_color"]); + ignore_schema(render_schema["properties/bg_color"]); + ignore_schema(render_schema["properties/shading"]); + ignore_schema(render_schema["properties/use_original_bounds"]); + ignore_schema(render_schema["properties/dataset_bounds"]); + ignore_schema(render_schema["properties/color_bar_position"]); + ignore_schema(render_schema["properties/tiled_rendering"]); + ignore_schema(render_schema["properties/tiled_rendering_type"]); + ignore_schema(render_schema["properties/tile_width"]); + ignore_schema(render_schema["properties/tile_height"]); + + conduit::Node &auto_camera_schema = render_schema["properties/auto_camera"]; + auto_camera_schema["type"] = "object"; + auto_camera_schema["additionalProperties"] = false; + ignore_schema(auto_camera_schema["properties/metric"]); + ignore_schema(auto_camera_schema["properties/field"]); + ignore_schema(auto_camera_schema["properties/samples"]); + ignore_schema(auto_camera_schema["properties/bins"]); + ignore_schema(auto_camera_schema["properties/height"]); + ignore_schema(auto_camera_schema["properties/width"]); + + // --- Camera --- + conduit::Node &camera_schema = render_schema["properties/camera"]; + camera_schema["type"] = "object"; + + conduit::Node &ascent_camera_schema = camera_schema["oneOf"].append(); + ascent_camera_schema["type"] = "object"; + ascent_camera_schema["additionalProperties"] = false; + ignore_schema(ascent_camera_schema["properties/2d"]); + ignore_schema(ascent_camera_schema["properties/look_at"]); + ignore_schema(ascent_camera_schema["properties/position"]); + ignore_schema(ascent_camera_schema["properties/up"]); + ignore_schema(ascent_camera_schema["properties/fov"]); + ignore_schema(ascent_camera_schema["properties/xpan"]); + ignore_schema(ascent_camera_schema["properties/ypan"]); + ignore_schema(ascent_camera_schema["properties/zoom"]); + ignore_schema(ascent_camera_schema["properties/near_plane"]); + ignore_schema(ascent_camera_schema["properties/far_plane"]); + ignore_schema(ascent_camera_schema["properties/azimuth"]); + ignore_schema(ascent_camera_schema["properties/elevation"]); + + conduit::Node &visit_camera_schema = camera_schema["oneOf"].append(); + visit_camera_schema["type"] = "object"; + visit_camera_schema["additionalProperties"] = false; + ignore_schema(visit_camera_schema["properties/windowCoords"]); + ignore_schema(visit_camera_schema["properties/view_normal"]); + ignore_schema(visit_camera_schema["properties/focus"]); + ignore_schema(visit_camera_schema["properties/view_up"]); + ignore_schema(visit_camera_schema["properties/view_angle"]); + ignore_schema(visit_camera_schema["properties/parallel_scale"]); + ignore_schema(visit_camera_schema["properties/near_plane"]); + ignore_schema(visit_camera_schema["properties/far_plane"]); + ignore_schema(visit_camera_schema["properties/image_pan"]); + ignore_schema(visit_camera_schema["properties/image_zoom"]); + ignore_schema(visit_camera_schema["properties/perspective"]); + ignore_schema(visit_camera_schema["properties/eye_angle"]); + ignore_schema(visit_camera_schema["properties/center_of_rotation_set"]); + ignore_schema(visit_camera_schema["properties/center_of_rotation"]); + ignore_schema(visit_camera_schema["properties/axis_3d_scale_flag"]); + ignore_schema(visit_camera_schema["properties/axis_3d_scale"]); + ignore_schema(visit_camera_schema["properties/shear"]); + ignore_schema(visit_camera_schema["properties/window_valid"]); + + array_schema(param_schema["properties/renders"], render_schema); } //----------------------------------------------------------------------------- @@ -1828,69 +1750,57 @@ CreatePlot::declare_interface(Node &i) i["type_name"] = "create_plot"; i["port_names"].append() = "a"; i["output_port"] = "true"; -} + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; -//----------------------------------------------------------------------------- -bool -CreatePlot::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); + string_schema(param_schema["properties/type"]); + ignore_schema(param_schema["properties/pipeline"]); + string_schema(param_schema["properties/topology"]); - bool res = check_string("type",params, info, true); + detail::color_table_schema(param_schema["properties/color_table"]); - bool is_mesh = false; + param_schema["required"].append() = "type"; - std::vector valid_paths; - valid_paths.push_back("type"); - valid_paths.push_back("pipeline"); - - res &= check_string("topology",params, info, false); - valid_paths.push_back("topology"); - - if(res) - { - if(params["type"].as_string() == "mesh") - { - is_mesh = true; - } - } - - if(!is_mesh) - { - res &= check_string("field", params, info, true); - valid_paths.push_back("field"); - valid_paths.push_back("points/radius"); - valid_paths.push_back("points/radius_delta"); - valid_paths.push_back("min_value"); - valid_paths.push_back("max_value"); - valid_paths.push_back("samples"); - } - else + // --- Is Mesh --- { - valid_paths.push_back("overlay"); - valid_paths.push_back("show_internal"); - } - - - std::vector ignore_paths; - ignore_paths.push_back("color_table"); + // properties are still added at the root level and then limited through forbids + ignore_schema(param_schema["properties/overlay"]); + ignore_schema(param_schema["properties/show_internal"]); - std::string surprises = surprise_check(valid_paths, ignore_paths, params); - - if(params.has_path("color_table")) - { - surprises += detail::check_color_table_surprises(params["color_table"]); + conduit::Node &mesh_schema = param_schema["oneOf"].append(); + mesh_schema["type"] = "object"; + mesh_schema["properties/type/constraints/const"] = "mesh"; + mesh_schema["constraints/forbid"] = "field"; + mesh_schema["constraints/forbid"] = "min_value"; + mesh_schema["constraints/forbid"] = "max_value"; + mesh_schema["constraints/forbid"] = "samples"; + mesh_schema["constraints/forbid"] = "points"; } - if(surprises != "") + // --- Is not Mesh --- { - res = false; - info["errors"].append() = surprises; + // properties are still added at the root level and then limited through forbids + ignore_schema(param_schema["properties/field"]); + ignore_schema(param_schema["properties/min_value"]); + ignore_schema(param_schema["properties/max_value"]); + ignore_schema(param_schema["properties/samples"]); + + conduit::Node &points_schema = param_schema["properties/points"]; + points_schema["type"] = "object"; + points_schema["additionalProperties"] = false; + ignore_schema(points_schema["properties/radius"]); + ignore_schema(points_schema["properties/radius_delta"]); + + conduit::Node ¬_mesh_schema = param_schema["oneOf"].append(); + not_mesh_schema["type"] = "object"; + not_mesh_schema["constraints/not_const/type"] = "mesh"; + not_mesh_schema["constraints/forbid"] = "overlay"; + not_mesh_schema["constraints/forbid"] = "show_internal"; + not_mesh_schema["required"].append() = "field"; } - - return res; } //----------------------------------------------------------------------------- diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rendering_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rendering_filters.hpp index 4d279744c..ecfa2fbbd 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rendering_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rendering_filters.hpp @@ -52,8 +52,6 @@ class ASCENT_API CreateRenders : public ::flow::Filter virtual ~CreateRenders(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -87,8 +85,6 @@ class ASCENT_API CreatePlot : public ::flow::Filter virtual ~CreatePlot(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rover_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rover_filters.cpp index 302786877..07f75f73b 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rover_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rover_filters.cpp @@ -97,346 +97,59 @@ RoverXRay::declare_interface(Node &i) i["type_name"] = "xray"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} - -//----------------------------------------------------------------------------- -bool -RoverXRay::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - // TODO: We want to be more rigorous about param checking at some point, so - // that rover can safely assume its inputs are valid - info.reset(); - - // Early return if none of the rover params were passed - if (!params.has_child("rover")) - { - info["errors"].append() = "Missing required string parameters: 'rover/absorption', 'rover/filename'"; - return false; - } - - const conduit::Node &n_rover = params["rover"]; - bool res = true; - - // - // Required rover parameters - // - - if (!n_rover.has_child("absorption")) - { - info["errors"].append() = "Missing required string parameter 'rover/absorption'"; - res = false; - } - else if (!n_rover["absorption"].dtype().is_string()) - { - info["errors"].append() = "Expected string parameter 'rover/absorption' is not a string"; - res = false; - } - else // (n_rover.has_child("absorption") && n_rover["absorption"].dtype().is_string()) - { - const std::string absorption = n_rover["absorption"].as_string(); - if (absorption.empty()) - { - info["errors"].append() = "Expected string parameter 'rover/absorption' cannot be an empty string"; - res = false; - } - } - - // This can either be a "filename" or a "/path/to/filename" - if (!n_rover.has_child("filename")) - { - info["errors"].append() = "Missing required string parameter 'rover/filename'"; - res = false; - } - else if (!n_rover["filename"].dtype().is_string()) - { - info["errors"].append() = "Expected string parameter 'rover/filename' is not a string"; - res = false; - } - else // (n_rover.has_child("filename") && n_rover["filename"].dtype().is_string()) - { - const std::string filename = n_rover["filename"].as_string(); - if (filename.empty()) - { - info["errors"].append() = "Expected string parameter 'rover/filename' cannot be an empty string"; - res = false; - } - } - - // - // Optional rover parameters - // - - if (n_rover.has_child("background_intensity")) - { - if (!n_rover["background_intensity"].dtype().is_number()) - { - info["errors"].append() = "Optional numeric parameter 'rover/background_intensity' is not numeric"; - res = false; - } - else // (n_rover["background_intensity"].dtype().is_number()) - { - const float64 background_intensity = n_rover["background_intensity"].to_float64(); - if (background_intensity < 0) - { - info["errors"].append() = "Optional numeric parameter 'rover/unit_scalar' must be positive"; - res = false; - } - } - } - - if (n_rover.has_child("divide_emis_by_absorb")) - { - if (!n_rover["divide_emis_by_absorb"].dtype().is_string()) - { - info["errors"].append() = "Optional bool string parameter 'rover/divide_emis_by_absorb' is not a string"; - res = false; - } - else // (n_rover["divide_emis_by_absorb"].dtype().is_string()) - { - const std::string divide_emis_by_absorb = n_rover["divide_emis_by_absorb"].as_string(); - if ("true" != divide_emis_by_absorb && "false" != divide_emis_by_absorb) - { - info["errors"].append() = "Optional bool string parameter 'rover/divide_emis_by_absorb' must be 'true' or 'false'"; - res = false; - } - } - } - - if (n_rover.has_child("emission")) - { - if (!n_rover["emission"].dtype().is_string()) - { - info["errors"].append() = "Optional string parameter 'rover/emission' is not a string"; - res = false; - } - else // (n_rover["emission"].dtype().is_string()) - { - const std::string emission = n_rover["emission"].as_string(); - if (emission.empty()) - { - info["errors"].append() = "Optional string parameter 'rover/emission' cannot be an empty string"; - res = false; - } - } - } - - if (n_rover.has_child("enable_rays_mesh")) - { - if (!n_rover["enable_rays_mesh"].dtype().is_string()) - { - info["errors"].append() = "Optional bool string parameter 'rover/enable_rays_mesh' is not a string"; - res = false; - } - else // (n_rover["enable_rays_mesh"].dtype().is_string()) - { - const std::string enable_rays_mesh = n_rover["enable_rays_mesh"].as_string(); - if ("true" != enable_rays_mesh && "false" != enable_rays_mesh) - { - info["errors"].append() = "Optional bool string parameter 'rover/enable_rays_mesh' must be 'true' or 'false'"; - res = false; - } - } - } - - const bool has_height = n_rover.has_child("height"); - if (has_height) - { - if (!n_rover["height"].dtype().is_integer()) - { - info["errors"].append() = "Optional integer parameter 'rover/height' is not an integer"; - res = false; - } - else // (n_rover["height"].dtype().is_integer()) - { - const int64 height = n_rover["height"].to_int64(); - if (height <= 0) - { - info["errors"].append() = "Optional integer parameter 'rover/height' must be greater than 0"; - res = false; - } - } - } - - if (n_rover.has_child("output_type")) - { - if (!n_rover["output_type"].dtype().is_string()) - { - info["errors"].append() = "Optional string parameter 'rover/output_type' is not a string"; - res = false; - } - else // (n_rover["output_type"].dtype().is_string()) - { - const std::string output_type = n_rover["output_type"].as_string(); - const std::string valid_types[] = {"hdf5", "yaml", "json", "png", "bov"}; - - if (std::find(std::begin(valid_types), std::end(valid_types), output_type) == std::end(valid_types)) - { - info["errors"].append() = "Optional string parameter 'rover/output_type' must be 'hdf5' or 'yaml' or 'json' or 'png' or 'bov'"; - res = false; - } - } - } - if (n_rover.has_child("precision")) - { - if (!n_rover["precision"].dtype().is_string()) - { - info["errors"].append() = "Optional string parameter 'rover/precision' is not a string"; - res = false; - } - else // (n_rover["precision"].dtype().is_string()) - { - const std::string precision = n_rover["precision"].as_string(); - if ("single" != precision && "double" != precision) - { - info["errors"].append() = "Optional string parameter 'rover/precision' must be 'single' or 'double'"; - res = false; - } - } - } - - const bool has_width = n_rover.has_child("width"); - if (has_width) - { - if (!n_rover["width"].dtype().is_integer()) - { - info["errors"].append() = "Optional integer parameter 'rover/width' is not an integer"; - res = false; - } - else // (n_rover["width"].dtype().is_integer()) - { - const int64 width = n_rover["width"].to_int64(); - if (width <= 0) - { - info["errors"].append() = "Optional integer parameter 'rover/width' must be greater than 0"; - res = false; - } - } - } - - // If either 'rover/width' or 'rover/height' are set, they must both be set - if (has_width && !has_height) - { - info["errors"].append() = "Optional integer parameter 'rover/width' requires 'rover/height' to also be set"; - res = false; - } - else if (!has_width && has_height) - { - info["errors"].append() = "Optional integer parameter 'rover/height' requires 'rover/width' to also be set"; - res = false; - } - - if (n_rover.has_child("unit_scalar")) - { - if (!n_rover["unit_scalar"].dtype().is_number()) - { - info["errors"].append() = "Optional numeric parameter 'rover/unit_scalar' is not numeric"; - res = false; - } - else // (n_rover["unit_scalar"].dtype().is_number() - { - const float64 unit_scalar = n_rover["unit_scalar"].to_float64(); - if (unit_scalar <= 0) - { - info["errors"].append() = "Optional numeric parameter 'rover/unit_scalar' must be greater than 0"; - res = false; - } - } - } - - // - // Optional image parameters - // - - if (params.has_child("image_params")) - { - // If any 'image_params' parameters are set, they must all be set - const conduit::Node &n_image = params["image_params"]; - - if (!n_image.has_child("log_scale")) - { - info["errors"].append() = "Missing bool string parameter 'image_params/log_scale'"; - res = false; - } - else if (!n_image["log_scale"].dtype().is_string()) - { - info["errors"].append() = "Optional bool string parameter 'image_params/log_scale' is not a string"; - res = false; - } - else // (n_image.has_child("log_scale") && n_image["log_scale"].dtype().is_string()) - { - const std::string log_scale = n_image["log_scale"].as_string(); - if ("true" != log_scale && "false" != log_scale) - { - info["errors"].append() = "Optional bool string parameter 'image_params/log_scale' must be 'true' or 'false'"; - res = false; - } - } - - if (!n_image.has_child("min_value")) - { - info["errors"].append() = "Missing numeric parameter 'image_params/min_value'"; - res = false; - } - else if (!n_image["min_value"].dtype().is_number()) - { - info["errors"].append() = "Expected numeric parameter 'image_params/min_value' is not numeric"; - res = false; - } - - if (!n_image.has_child("max_value")) - { - info["errors"].append() = "Missing numeric parameter 'image_params/max_value'"; - res = false; - } - else if (!n_image["max_value"].dtype().is_number()) - { - info["errors"].append() = "Expected numeric parameter 'image_params/max_value' is not numeric"; - res = false; - } - } - - // - // Surprise check - // - - const std::vector valid_paths = { - "camera/azimuth", - "camera/elevation", - "camera/far_plane", - "camera/fov", - "camera/look_at", - "camera/near_plane", - "camera/position", - "camera/up", - "camera/xpan", - "camera/ypan", - "camera/zoom", - "image_params/log_scale", - "image_params/max_value", - "image_params/min_value", - "rover/absorption", - "rover/background_intensity", - "rover/divide_emis_by_absorb", - "rover/emission", - "rover/enable_rays_mesh", - "rover/filename", - "rover/height", - "rover/output_type", - "rover/precision", - "rover/width", - "rover/unit_scalar" - }; - - const std::string surprises = surprise_check(valid_paths, params); - if (!surprises.empty()) - { - info["errors"].append() = surprises; - res = false; - } - - return res; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; + + string_schema(param_schema["properties/condition"]); + string_schema(param_schema["properties/callback"]); + string_schema(param_schema["properties/actions_file"]); + array_schema(param_schema["properties/actions_files"]); + array_schema(param_schema["properties/actions"]); + + // --- Rover --- + conduit::Node &rover_schema = param_schema["properties/rover"]; + string_schema(rover_schema["properties/absorption"], 1); + string_schema(rover_schema["properties/filename"], 1); + number_schema(rover_schema["properties/background_intensity"], false, 0); + bool_schema(rover_schema["properties/divide_emis_by_absorb"]); + string_schema(rover_schema["properties/emission"], 1); + bool_schema(rover_schema["properties/enable_rays_mesh"]); + integer_schema(rover_schema["properties/height"], false, 0, std::numeric_limits::max(), 0); + integer_schema(rover_schema["properties/width"], false, 0, std::numeric_limits::max(), 0); + string_enum_schema(rover_schema["properties/output_type"], {"hdf5", "yaml", "json", "png", "bov"}); + string_enum_schema(rover_schema["properties/precision"], {"single", "double"}); + number_schema(rover_schema["properties/unit_scalar"], false, 0, std::numeric_limits::max(), 0); + + rover_schema["constraints/dependencies/height"].append() = "width"; + rover_schema["constraints/dependencies/width"].append() = "height"; + + rover_schema["required"].append() = "absorption"; + rover_schema["required"].append() = "filename"; + + // --- Image --- + conduit::Node &image_schema = param_schema["properties/image_params"]; + bool_schema(image_schema["properties/log_scale"]); + number_schema(image_schema["properties/min_value"]); + number_schema(image_schema["properties/max_value"]); + + // --- Camera --- + conduit::Node &camera_schema = param_schema["properties/camera"]; + ignore_schema(camera_schema["properties/azimuth"]); + ignore_schema(camera_schema["properties/elevation"]); + ignore_schema(camera_schema["properties/far_plane"]); + ignore_schema(camera_schema["properties/near_plane"]); + ignore_schema(camera_schema["properties/fov"]); + ignore_schema(camera_schema["properties/look_at"]); + ignore_schema(camera_schema["properties/position"]); + ignore_schema(camera_schema["properties/up"]); + ignore_schema(camera_schema["properties/xpan"]); + ignore_schema(camera_schema["properties/ypan"]); + ignore_schema(camera_schema["properties/zoom"]); + + param_schema["required"].append() = "rover"; } //----------------------------------------------------------------------------- @@ -587,43 +300,18 @@ RoverVolume::declare_interface(Node &i) i["type_name"] = "rover_volume"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} -//----------------------------------------------------------------------------- -bool -RoverVolume::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = true; - - if(! params.has_child("field") || - ! params["field"].dtype().is_string() ) - { - info["errors"].append() = "Missing required string parameter 'field'"; - res = false; - } + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - if(! params.has_child("filename") || - ! params["filename"].dtype().is_string() ) - { - info["errors"].append() = "Missing required string parameter 'filename'"; - res = false; - } - - if( params.has_child("precision") && - ! params["precision"].dtype().is_string() ) - { - info["errors"].append() = "Optional parameter 'precision' must be a string"; - std::string prec = params["precision"].as_string(); - if(prec != "single" || prec != "double") - { - info["errors"].append() = "Parameter 'precision' must be 'single' or 'double'"; - } - res = false; - } + string_schema(param_schema["properties/field"]); + string_schema(param_schema["properties/filename"]); + string_enum_schema(param_schema["properties/precision"], {"single", "double"}); - return res; + param_schema["required"].append() = "field"; + param_schema["required"].append() = "filename"; } //----------------------------------------------------------------------------- diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rover_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rover_filters.hpp index 86a543094..54bc1612e 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rover_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_rover_filters.hpp @@ -50,8 +50,6 @@ class ASCENT_API RoverXRay: public ::flow::Filter virtual ~RoverXRay(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; @@ -63,8 +61,6 @@ class ASCENT_API RoverVolume : public ::flow::Filter virtual ~RoverVolume(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; #endif diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_steering_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_steering_filters.cpp index 5abbd16d2..d40c06481 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_steering_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_steering_filters.cpp @@ -73,25 +73,12 @@ Steering::declare_interface(Node &i) i["type_name"] = "steering"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} -//----------------------------------------------------------------------------- -bool -Steering::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - bool res = true; - // This optional parameter exists for automated testing purposes - if(params.has_child("explicit_command")) - { - if(!params["explicit_command"].dtype().is_string()) - { - info["errors"].append() = "optional entry 'explicit_command' must" - " be a string"; - res = false; - } - } - return res; + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + + string_schema(param_schema["properties/explicit_command"]); } //----------------------------------------------------------------------------- diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_steering_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_steering_filters.hpp index 518856674..a08de3269 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_steering_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_steering_filters.hpp @@ -55,8 +55,6 @@ class ASCENT_API Steering : public ::flow::Filter Steering(); ~Steering(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); private: std::map> m_commands; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_trigger_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_trigger_filters.cpp index 850aabd29..5e8073f44 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_trigger_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_trigger_filters.cpp @@ -85,87 +85,35 @@ BasicTrigger::declare_interface(Node &i) i["type_name"] = "basic_trigger"; i["port_names"].append() = "in"; i["output_port"] = "false"; -} -//----------------------------------------------------------------------------- -bool -BasicTrigger::verify_params(const conduit::Node ¶ms, - conduit::Node &info) -{ - info.reset(); - bool res = check_string("condition",params, info, false); - res &= check_string("callback",params, info, false); - res &= check_string("actions_file",params, info, false); - res &= check_list("actions_files",params, info, false); - res &= check_list("actions",params, info, false); - - bool has_condition = params.has_child("condition"); - bool has_callback = params.has_child("callback"); - bool has_actions = params.has_child("actions"); - bool has_actions_file = params.has_child("actions_file"); - bool has_actions_files = params.has_child("actions_files"); - - if( has_condition && has_callback ) - { - res = false; - info["errors"].append() = "Both `condition` and `callback` are " - "present. Choose one or the other."; - } + // ----------- Define Param Schema ----------- + conduit::Node ¶m_schema = i["param_schema"]; + param_schema["type"] = "object"; + param_schema["additionalProperties"] = false; - if( ! (has_condition || has_callback) ) { - res = false; - info["errors"].append() = "No `condition` or `callback` provided. " - "Choose please provide trigger `condition`" - " or `callback`"; - } + string_schema(param_schema["properties/condition"]); + string_schema(param_schema["properties/callback"]); - if( has_actions_file && has_actions_files ) - { - res = false; - info["errors"].append() = "Both `actions_file` and `actions_files` are " - "present. Choose one or the other."; + conduit::Node &trigger_schema = param_schema["allOf"].append(); + trigger_schema["constraints/exclusiveChildren"].append() = "condition"; + trigger_schema["constraints/exclusiveChildren"].append() = "callback"; + trigger_schema["constraints/allowNoneInExclusiveGroup"] = false; } - - if(has_actions && (has_actions_file || has_actions_files)) { - res = false; - info["errors"].append() = "Both `actions` and `actions_file(s)` are " - "present. Choose one or the other."; + conduit::Node actions_string_schema; + array_schema(param_schema["properties/actions_files"], string_schema(actions_string_schema)); + array_schema(param_schema["properties/actions"]); + string_schema(param_schema["properties/actions_file"]); + + conduit::Node &action_schema = param_schema["allOf"].append(); + action_schema["constraints/exclusiveChildren"].append() = "actions_file"; + action_schema["constraints/exclusiveChildren"].append() = "actions_files"; + action_schema["constraints/exclusiveChildren"].append() = "actions"; + action_schema["constraints/allowNoneInExclusiveGroup"] = false; } - - if(!has_actions && !(has_actions_file || has_actions_files)) - { - res = false; - info["errors"].append() = "No trigger actions provided. Please " - "specify either 'actions_file(s)' or " - "'actions'."; - } - - std::vector valid_paths; - valid_paths.push_back("condition"); - valid_paths.push_back("callback"); - valid_paths.push_back("actions_file"); - valid_paths.push_back("actions_files"); - valid_paths.push_back("actions"); - - std::vector ignore_paths; - // don't go down the actions or actions_files path - ignore_paths.push_back("actions"); - ignore_paths.push_back("actions_files"); - - std::string surprises = surprise_check(valid_paths, ignore_paths,params); - - if(surprises != "") - { - res = false; - info["errors"].append() = surprises; - } - - return res; } - //----------------------------------------------------------------------------- void BasicTrigger::execute() diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_trigger_filters.hpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_trigger_filters.hpp index bb5a1538b..dcb14c1d9 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_trigger_filters.hpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_trigger_filters.hpp @@ -51,8 +51,6 @@ class ASCENT_API BasicTrigger : public ::flow::Filter ~BasicTrigger(); virtual void declare_interface(conduit::Node &i); - virtual bool verify_params(const conduit::Node ¶ms, - conduit::Node &info); virtual void execute(); }; diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp index bb884c109..612efb1f5 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp @@ -4444,9 +4444,7 @@ VTKHTransform::declare_interface(Node &i) // --- matrix --- conduit::Node matrix_item_schema; - conduit::Node &matrix_schema = array_schema(param_schema["properties/matrix"], number_schema(matrix_item_schema, true)); - matrix_schema["minItems"] = 16; - matrix_schema["maxItems"] = 16; + conduit::Node &matrix_schema = array_schema(param_schema["properties/matrix"], number_schema(matrix_item_schema, true), 16, 16); } //----------------------------------------------------------------------------- diff --git a/src/libs/flow/flow_schema_validator.cpp b/src/libs/flow/flow_schema_validator.cpp index 26505b48d..29f5c2c80 100644 --- a/src/libs/flow/flow_schema_validator.cpp +++ b/src/libs/flow/flow_schema_validator.cpp @@ -16,6 +16,7 @@ // standard lib includes #include #include +#include //----------------------------------------------------------------------------- // -- begin flow -- @@ -82,6 +83,10 @@ bool check_type(const conduit::Node &input, { ok = data_type.is_number(); } + else if(schema_defined_type == "integer") + { + ok = data_type.is_integer(); + } else if(schema_defined_type == "array") { ok = (data_type.is_list() || @@ -104,6 +109,144 @@ bool check_type(const conduit::Node &input, return ok; } +bool validate_string(const conduit::Node &schema, + const conduit::Node &input, + conduit::Node &info, + const std::string &path) +{ + if(!input.dtype().is_string()) return true; + + const std::string s = input.as_string(); + bool ok = true; + + if(schema.has_child("minLength")) + { + int mn = schema["minLength"].to_int(); + if((int)s.size() < mn) + { + add_error(info, "String at '" + (path.empty() ? "" : path) + + "' is shorter than minLength=" + std::to_string(mn)); + ok = false; + } + } + + if(schema.has_child("maxLength")) + { + int mx = schema["maxLength"].to_int(); + if((int)s.size() > mx) + { + add_error(info, "String at '" + (path.empty() ? "" : path) + + "' is longer than maxLength=" + std::to_string(mx)); + ok = false; + } + } + + if(schema.has_child("pattern")) + { + const std::string pattern = schema["pattern"].as_string(); + const std::string loc = path.empty() ? "" : path; + + try + { + const std::regex re(pattern); + if(!std::regex_match(s, re)) + { + add_error(info, "String at '" + loc + + "' does not match pattern '" + pattern + "'"); + ok = false; + } + } + catch(const std::regex_error &) + { + add_error(info, "Schema at '" + loc + + "' has invalid regex pattern '" + pattern + "'"); + ok = false; + } + } + + return ok; +} + +bool validate_enum(const conduit::Node &schema, + const conduit::Node &input, + conduit::Node &info, + const std::string &path) +{ + const conduit::Node *e = nullptr; + if(schema.has_child("enum")) e = &schema["enum"]; + else return true; + + if(!input.dtype().is_string()) return true; + + const std::string got = input.as_string(); + for(conduit::index_t i = 0; i < e->number_of_children(); ++i) + { + if(got == e->child(i).as_string()) return true; + } + + add_error(info, "Value not in enum at '" + + (path.empty() ? "" : path) + + "': got '" + got + "'"); + return false; +} + +bool validate_number(const conduit::Node &schema, + const conduit::Node &input, + conduit::Node &info, + const std::string &path) +{ + if(!input.dtype().is_number()) return true; + + const double v = input.to_float64(); + bool ok = true; + + if(schema.has_child("minimum")) + { + double mn = schema["minimum"].to_float64(); + if(v < mn) + { + add_error(info, "Number at '" + (path.empty() ? "" : path) + + "' must be >= " + std::to_string(mn)); + ok = false; + } + } + + if(schema.has_child("exclusiveMinimum")) + { + double mn = schema["exclusiveMinimum"].to_float64(); + if(v <= mn) + { + add_error(info, "Number at '" + (path.empty() ? "" : path) + + "' must be > " + std::to_string(mn)); + ok = false; + } + } + + if(schema.has_child("maximum")) + { + double mx = schema["maximum"].to_float64(); + if(v > mx) + { + add_error(info, "Number at '" + (path.empty() ? "" : path) + + "' must be <= " + std::to_string(mx)); + ok = false; + } + } + + if(schema.has_child("exclusiveMaximum")) + { + double mx = schema["exclusiveMaximum"].to_float64(); + if(v >= mx) + { + add_error(info, "Number at '" + (path.empty() ? "" : path) + + "' must be < " + std::to_string(mx)); + ok = false; + } + } + + return ok; +} + // ---------- Object-Specific Validation Helpers ---------- // Earlier declaration so validate node can be refrenced by helpers. @@ -391,6 +534,22 @@ bool validate_exclusive_children(const conduit::Node &schema, return false; } +static bool validate_all_of(const conduit::Node &schema, + const conduit::Node &input, + conduit::Node &info, + const std::string &path) +{ + if(!schema.has_child("allOf")) return true; + + bool ok = true; + const conduit::Node &opts = schema["allOf"]; + for(conduit::index_t i = 0; i < opts.number_of_children(); ++i) + { + ok = validate_node(opts.child(i), input, info, path) && ok; + } + return ok; +} + bool validate_one_of(const conduit::Node &schema, const conduit::Node &input, conduit::Node &info, @@ -441,7 +600,7 @@ bool validate_one_of(const conduit::Node &schema, oss << "oneOf violation at '" << (path.empty() ? "" : path) << "': "; if(matches == 0) { - oss << "input did not match any supported schemas"; + oss << "input did not match any supported schema"; } else { @@ -528,6 +687,7 @@ bool validate_object(const conduit::Node &schema, ok = validate_properties(schema, input, info, path) && ok; // Finally, enforce oneOf (treating options as extra constraints on this same object) + ok = validate_all_of(schema, input, info, path) && ok; ok = validate_one_of(schema, input, info, path) && ok; ok = validate_any_of(schema, input, info, path) && ok; @@ -600,11 +760,11 @@ bool validate_array(const conduit::Node &schema, if(!schema.has_child("items")) { - return true; // unconstrained items + return ok; // unconstrained items } const conduit::Node &item_schema = schema["items"]; - if(data_type.is_list()) + if(data_type.is_list() || data_type.is_object()) { for(conduit::index_t i = 0; i < count; ++i) { @@ -643,6 +803,18 @@ bool validate_node(const conduit::Node &schema, ok = check_type(input, schema, info, path) && ok; ok = validate_const(schema, input, info, path) && ok; + ok = validate_enum(schema, input, info, path) && ok; + + if(schema_defined_type == "string") + { + ok = validate_string(schema, input, info, path) && ok; + } + + if(schema_defined_type == "number" || schema_defined_type == "integer") + { + ok = validate_number(schema, input, info, path) && ok; + } + if(!ok) { return false; // type mismatch stops recursion @@ -657,6 +829,7 @@ bool validate_node(const conduit::Node &schema, return validate_array(schema, input, info, path); } + ok = validate_all_of(schema, input, info, path) && ok; ok = validate_one_of(schema, input, info, path) && ok; ok = validate_any_of(schema, input, info, path) && ok; ok = validate_format(schema, input, info, path) && ok; diff --git a/src/tests/ascent/t_ascent_render_3d.cpp b/src/tests/ascent/t_ascent_render_3d.cpp index c61857eea..4accfc69b 100644 --- a/src/tests/ascent/t_ascent_render_3d.cpp +++ b/src/tests/ascent/t_ascent_render_3d.cpp @@ -4020,14 +4020,14 @@ TEST(ascent_render_3d, test_render_invalid_camera) } catch(conduit::Error &err) { - if (err.message().find("Cameras must follow either an ascent format or a visit format, not both.") != std::string::npos) + if (err.message().find("input did not match any supported schema") != std::string::npos) { error_occured = true; } else { std::cout << "The error that was thrown did not match the expected " - << "'Cameras must follow either an ascent format or a visit format, not both.' error" << std::endl; + << "'input did not match any supported schema' error" << std::endl; std::cout << err.message() << std::endl; }