diff --git a/.github/workflows/subsurface.yml b/.github/workflows/subsurface.yml index 763dd39f0e..2f35bb9313 100644 --- a/.github/workflows/subsurface.yml +++ b/.github/workflows/subsurface.yml @@ -73,10 +73,10 @@ jobs: env: # If you want the CI to (temporarily) run against your fork of the testdada, # change the value her from "equinor" to your username. - TESTDATA_REPO_OWNER: CeetronSolutions + TESTDATA_REPO_OWNER: equinor # If you want the CI to (temporarily) run against another branch than master, # change the value her from "master" to the relevant branch name. - TESTDATA_REPO_BRANCH: EQ_293-VectorCalculatorConfig + TESTDATA_REPO_BRANCH: master run: | git clone --depth 1 --branch $TESTDATA_REPO_BRANCH https://github.com/$TESTDATA_REPO_OWNER/webviz-subsurface-testdata.git # Copy any clientside script to the test folder before running tests diff --git a/webviz_subsurface/_utils/vector_calculator.py b/webviz_subsurface/_utils/vector_calculator.py index 5b53550232..280748bb73 100644 --- a/webviz_subsurface/_utils/vector_calculator.py +++ b/webviz_subsurface/_utils/vector_calculator.py @@ -15,6 +15,8 @@ VariableVectorMapInfo, ) +from .vector_selector import is_vector_name_in_vector_selector_data + if sys.version_info >= (3, 8): from typing import TypedDict else: @@ -22,7 +24,7 @@ # JSON Schema for predefined expressions configuration # Used as schema input for json_schema.validate() -PREDEFINED_EXPRESSIONS_JSON_SCHEMA: dict = { +PREDEFINED_EXPRESSIONS_JSON_SCHEMA = { "type": "object", "additionalProperties": { "type": "object", @@ -129,7 +131,7 @@ def validate_predefined_expression( ) invalid_vectors: List[str] = [] for vector_name in variable_vector_dict.values(): - if not is_vector_name_existing(vector_name, vector_data): + if not is_vector_name_in_vector_selector_data(vector_name, vector_data): invalid_vectors.append(vector_name) if len(invalid_vectors) > 1: message = ( @@ -177,36 +179,20 @@ def expressions_from_config( expression_dict = { "name": expression, "expression": expressions[expression]["expression"], - "id": f"{uuid4()}", + "id": str(uuid4()), "variableVectorMap": variable_vector_map_from_dict( expressions[expression]["variableVectorMap"] ), "isValid": False, # Set False and validate in seperate operation "isDeletable": False, } - if "description" in expressions[expression].keys(): + if "description" in expressions[expression]: expression_dict["description"] = expressions[expression]["description"] output.append(expression_dict) return output -def is_vector_name_existing(name: str, vector_data: list) -> bool: - nodes = name.split(":") - current_child_list = vector_data - for node in nodes: - found = False - for child in current_child_list: - if child["name"] == node: - children = child["children"] - current_child_list = children if children is not None else [] - found = True - break - if not found: - return False - return found - - def get_expression_from_name( name: str, expressions: List[ExpressionInfo] ) -> Union[ExpressionInfo, None]: @@ -235,14 +221,14 @@ def get_custom_vector_definitions_from_expressions( Uses expression str as description if optional expression description str does not exist. """ - output: dict = {} + output = {} for expression in expressions: name = expression["name"] key = name.split(":")[0] vector_type = "calculated" description = ( expression["expression"] - if not "description" in dict(expression).keys() + if not "description" in expression else expression["description"] ) output[key] = {"type": vector_type, "description": description} diff --git a/webviz_subsurface/_utils/vector_selector.py b/webviz_subsurface/_utils/vector_selector.py new file mode 100644 index 0000000000..b04ef026a4 --- /dev/null +++ b/webviz_subsurface/_utils/vector_selector.py @@ -0,0 +1,47 @@ +def add_vector_to_vector_selector_data( + vector_selector_data: list, + vector: str, + description: str, + description_at_last_node: bool = False, +) -> None: + nodes = vector.split(":") + current_child_list = vector_selector_data + for index, node in enumerate(nodes): + found = False + for child in current_child_list: + if child["name"] == node: + children = child["children"] + current_child_list = children if children is not None else [] + found = True + break + if not found: + description_text = description if index == 0 else "" + if description_at_last_node: + description_text = description if index == len(nodes) - 1 else "" + current_child_list.append( + { + "name": node, + "description": description_text, + "children": [] if index < len(nodes) - 1 else None, + } + ) + children = current_child_list[-1]["children"] + current_child_list = children if children is not None else [] + + +def is_vector_name_in_vector_selector_data( + name: str, vector_selector_data: list +) -> bool: + nodes = name.split(":") + current_child_list = vector_selector_data + for node in nodes: + found = False + for child in current_child_list: + if child["name"] == node: + children = child["children"] + current_child_list = children if children is not None else [] + found = True + break + if not found: + return False + return found diff --git a/webviz_subsurface/plugins/_reservoir_simulation_timeseries.py b/webviz_subsurface/plugins/_reservoir_simulation_timeseries.py index c10b1327ea..cbe30fed63 100644 --- a/webviz_subsurface/plugins/_reservoir_simulation_timeseries.py +++ b/webviz_subsurface/plugins/_reservoir_simulation_timeseries.py @@ -55,13 +55,17 @@ calc_from_cumulatives, rename_vec_from_cum, ) + +from .._utils.vector_selector import ( + add_vector_to_vector_selector_data, + is_vector_name_in_vector_selector_data, +) from .._utils.vector_calculator import ( expressions_from_config, get_calculated_units, get_calculated_vector_df, get_expression_from_name, get_selected_expressions, - is_vector_name_existing, validate_predefined_expression, get_custom_vector_definitions_from_expressions, ) @@ -195,6 +199,8 @@ def __init__( / "block_options.css" ) + # Temporary css, pending on new wcc modal component. + # See: https://github.com/equinor/webviz-core-components/issues/163 WEBVIZ_ASSETS.add( Path(webviz_subsurface.__file__).parent / "_assets" / "css" / "modal.css" ) @@ -259,7 +265,7 @@ def __init__( self.vector_data: list = [] for vec in self.smry_cols: split = vec.split(":") - self._add_vector( + add_vector_to_vector_selector_data( self.vector_data, vec, simulation_vector_description(split[0]) ) @@ -276,12 +282,12 @@ def __init__( avgrate_split = avgrate_vec.split(":") interval_split = interval_vec.split(":") - self._add_vector( + add_vector_to_vector_selector_data( self.vector_data, avgrate_vec, f"{simulation_vector_description(avgrate_split[0])} ({avgrate_vec})", ) - self._add_vector( + add_vector_to_vector_selector_data( self.vector_data, interval_vec, f"{simulation_vector_description(interval_split[0])} ({interval_vec})", @@ -355,37 +361,6 @@ def __init__( self.allow_delta = len(self.ensembles) > 1 self.set_callbacks(app) - @staticmethod - def _add_vector( - vector_data: list, - vector: str, - description: str, - description_at_last_node: bool = False, - ) -> None: - nodes = vector.split(":") - current_child_list = vector_data - for index, node in enumerate(nodes): - found = False - for child in current_child_list: - if child["name"] == node: - children = child["children"] - current_child_list = children if children is not None else [] - found = True - break - if not found: - description_text = description if index == 0 else "" - if description_at_last_node: - description_text = description if index == len(nodes) - 1 else "" - current_child_list.append( - { - "name": node, - "description": description_text, - "children": [] if index < len(nodes) - 1 else None, - } - ) - children = current_child_list[-1]["children"] - current_child_list = children if children is not None else [] - @staticmethod def _add_expression( expression_data: list, @@ -393,8 +368,8 @@ def _add_expression( description: Optional[str] = None, ) -> None: description_str = description if description is not None else "" - ReservoirSimulationTimeSeries._add_vector( - vector_data=expression_data, + add_vector_to_vector_selector_data( + vector_selector_data=expression_data, vector=name, description=description_str, description_at_last_node=True, @@ -800,7 +775,7 @@ def _get_valid_vector_selections( ) # Append if vector name exist among data - if new_vector is not None and is_vector_name_existing( + if new_vector is not None and is_vector_name_in_vector_selector_data( new_vector, vector_data ): valid_selections.append(new_vector)