def test_simulation_vector_description_existing_vector() -> None: # Verify test vector exist in VectorDefinitions assert "WOPT" in VectorDefinitions # Test WITHOUT vector definitions argument assert simulation_vector_description("WOPT:A1") == "Oil Production Total, well A1" assert ( simulation_vector_description("PER_DAY_WOPT:A1") == "Average Oil Production Total Per day, well A1" ) assert ( simulation_vector_description("PER_INTVL_WOPT:A1") == "Interval Oil Production Total, well A1" ) assert ( simulation_vector_description("AVG_WOPT:A1") == "Average Oil Production Total, well A1" ) assert ( simulation_vector_description("INTVL_WOPT:A1") == "Interval Oil Production Total, well A1" ) # Test WITH vector definitions argument vector_definitions = { "WOPT": VectorDefinition(type="well", description="Test Description"), } assert ( simulation_vector_description("WOPT:A1", vector_definitions) == "Test Description, well A1" ) assert ( simulation_vector_description("PER_DAY_WOPT:A1", vector_definitions) == "Average Test Description Per day, well A1" ) assert ( simulation_vector_description("PER_INTVL_WOPT:A1", vector_definitions) == "Interval Test Description, well A1" ) assert ( simulation_vector_description("AVG_WOPT:A1", vector_definitions) == "Average Test Description, well A1" ) assert ( simulation_vector_description("INTVL_WOPT:A1", vector_definitions) == "Interval Test Description, well A1" )
def test_simulation_vector_description_non_existing_vector() -> None: # Verify test vector does not exist in VectorDefinitions assert "Custom" not in VectorDefinitions # Test WITHOUT vector definitions argument assert simulation_vector_description("Custom:A1") == "Custom:A1" assert ( simulation_vector_description("PER_DAY_Custom:A1") == "Average Custom:A1 Per day" ) assert simulation_vector_description("PER_INTVL_Custom:A1") == "Interval Custom:A1" assert simulation_vector_description("AVG_Custom:A1") == "Average Custom:A1" assert simulation_vector_description("INTVL_Custom:A1") == "Interval Custom:A1" # Test WITH vector definitions argument vector_definitions = { "Custom": VectorDefinition(type="field", description="Custom Description"), } assert ( simulation_vector_description("Custom:A1", vector_definitions) == "Custom Description, field A1" ) assert ( simulation_vector_description("PER_DAY_Custom:A1", vector_definitions) == "Average Custom Description Per day, field A1" ) assert ( simulation_vector_description("PER_INTVL_Custom:A1", vector_definitions) == "Interval Custom Description, field A1" ) assert ( simulation_vector_description("AVG_Custom:A1", vector_definitions) == "Average Custom Description, field A1" ) assert ( simulation_vector_description("INTVL_Custom:A1", vector_definitions) == "Interval Custom Description, field A1" )
def create_vector_plot_titles_from_provider_set( vector_names: List[str], expressions: List[ExpressionInfo], provider_set: ProviderSet, ) -> Dict[str, str]: """Create plot titles for vectors Create plot titles for vectors by use of provider set metadata and list of calculation expressions `Return:` * Dictionary with vector names as keys and the corresponding title as value """ vector_title_dict: Dict[str, str] = {} all_vector_names = provider_set.all_vector_names() for vector_name in vector_names: vector = vector_name if vector.startswith("AVG_"): vector = vector.lstrip("AVG_") if vector.startswith("INTVL_"): vector = vector.lstrip("INTVL_") if vector in all_vector_names: metadata = provider_set.vector_metadata(vector) title = simulation_vector_description(vector_name) if metadata and metadata.unit: title = (f"{simulation_vector_description(vector_name)}" f" [{simulation_unit_reformat(metadata.unit)}]") vector_title_dict[vector_name] = title else: expression = get_expression_from_name(vector_name, expressions) if expression: unit = create_calculated_unit_from_provider_set( expression, provider_set) if unit: # TODO: Expression description instead of vector name in title? vector_title_dict[vector_name] = f"{vector_name} [{unit}]" else: vector_title_dict[vector_name] = vector_name else: vector_title_dict[vector_name] = vector_name return vector_title_dict
def __init__( self, app: dash.Dash, webviz_settings: WebvizSettings, ensembles: Optional[list] = None, rel_file_pattern: str = "share/results/unsmry/*.arrow", perform_presampling: bool = False, obsfile: Path = None, options: dict = None, sampling: str = Frequency.MONTHLY.value, predefined_expressions: str = None, user_defined_vector_definitions: str = None, line_shape_fallback: str = "linear", ) -> None: super().__init__() # NOTE: 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") self._webviz_settings = webviz_settings self._obsfile = obsfile # Retrieve user defined vector descriptions from configuration and validate self._user_defined_vector_descriptions_path = ( None if user_defined_vector_definitions is None else webviz_settings.shared_settings["user_defined_vector_definitions"] [user_defined_vector_definitions]) self._user_defined_vector_definitions: Dict[ str, wsc. VectorDefinition] = create_user_defined_vector_descriptions_from_config( get_path(self._user_defined_vector_descriptions_path) if self. _user_defined_vector_descriptions_path else None) self._custom_vector_definitions = copy.deepcopy( self._user_defined_vector_definitions) self._line_shape_fallback = set_simulation_line_shape_fallback( line_shape_fallback) # Must define valid freqency! if Frequency.from_string_value(sampling) is None: raise ValueError( 'Sampling frequency conversion is "None", i.e. Raw sampling, and ' "is not supported by plugin yet!") self._sampling = Frequency(sampling) self._presampled_frequency = None # TODO: Update functionality when allowing raw data and csv file input # NOTE: If csv is implemented-> handle/disable statistics, PER_INTVL_, PER_DAY_, delta # ensemble, etc. if ensembles is not None: ensemble_paths: Dict[str, Path] = { ensemble_name: webviz_settings.shared_settings["scratch_ensembles"] [ensemble_name] for ensemble_name in ensembles } if perform_presampling: self._presampled_frequency = self._sampling self._input_provider_set = create_presampled_provider_set_from_paths( ensemble_paths, rel_file_pattern, self._presampled_frequency) else: self._input_provider_set = create_lazy_provider_set_from_paths( ensemble_paths, rel_file_pattern) else: raise ValueError('Incorrect argument, must provide "ensembles"') if not self._input_provider_set: raise ValueError( "Initial provider set is undefined, and ensemble summary providers" " are not instanciated for plugin") self._theme = webviz_settings.theme self._observations = {} if self._obsfile: self._observations = check_and_format_observations( get_path(self._obsfile)) # NOTE: Initially keep set of all vector names - can make dynamic if wanted? vector_names = self._input_provider_set.all_vector_names() non_historical_vector_names = [ vector for vector in vector_names if historical_vector(vector, None, False) not in vector_names ] # NOTE: Initially: With set of vector names, the vector selector data is static # Can be made dynamic based on selected ensembles - i.e. vectors present among # selected providers? self._vector_selector_base_data: list = [] self._vector_calculator_data: list = [] for vector in non_historical_vector_names: add_vector_to_vector_selector_data( self._vector_selector_base_data, vector, ) # Only vectors from providers are provided to vector calculator add_vector_to_vector_selector_data( self._vector_calculator_data, vector, ) metadata = (self._input_provider_set.vector_metadata(vector) if self._input_provider_set else None) if metadata and metadata.is_total: # Get the likely name for equivalent rate vector and make dropdown options. # Requires that the time_index was either defined or possible to infer. per_day_vec = create_per_day_vector_name(vector) per_intvl_vec = create_per_interval_vector_name(vector) add_vector_to_vector_selector_data( self._vector_selector_base_data, per_day_vec, ) add_vector_to_vector_selector_data( self._vector_selector_base_data, per_intvl_vec, ) # Add vector base to custom vector definition if not existing vector_base = vector.split(":")[0] _definition = wsc.VectorDefinitions.get(vector_base, None) _type = _definition["type"] if _definition else "others" per_day_vec_base = per_day_vec.split(":")[0] per_intvl_vec_base = per_intvl_vec.split(":")[0] if per_day_vec_base not in self._custom_vector_definitions: self._custom_vector_definitions[ per_day_vec_base] = wsc.VectorDefinition( type=_type, description=simulation_vector_description( per_day_vec_base, self._user_defined_vector_definitions), ) if per_intvl_vec_base not in self._custom_vector_definitions: self._custom_vector_definitions[ per_intvl_vec_base] = wsc.VectorDefinition( type=_type, description=simulation_vector_description( per_intvl_vec_base, self._user_defined_vector_definitions), ) # Retreive predefined expressions from configuration and validate self._predefined_expressions_path = ( None if predefined_expressions is None else webviz_settings. shared_settings["predefined_expressions"][predefined_expressions]) self._predefined_expressions = expressions_from_config( get_path(self._predefined_expressions_path) if self. _predefined_expressions_path else None) for expression in self._predefined_expressions: valid, message = validate_predefined_expression( expression, self._vector_selector_base_data) if not valid: warnings.warn(message) expression["isValid"] = valid # Add expressions to custom vector definitions self._custom_vector_definitions_base = copy.deepcopy( self._custom_vector_definitions) _custom_vector_definitions_from_expressions = ( get_vector_definitions_from_expressions( self._predefined_expressions)) for key, value in _custom_vector_definitions_from_expressions.items(): if key not in self._custom_vector_definitions: self._custom_vector_definitions[key] = value # Create initial vector selector data with predefined expressions self._initial_vector_selector_data = copy.deepcopy( self._vector_selector_base_data) add_expressions_to_vector_selector_data( self._initial_vector_selector_data, self._predefined_expressions) plot_options = options if options else {} self._initial_visualization_selection = VisualizationOptions( plot_options.get("visualization", "statistics")) # Initial selected vectors - NB: {vector1, vector2, vector3} is deprecated! initial_vectors: List[str] = plot_options.get("vectors", []) # TODO: Remove when depretaced code is not utilized anymore if "vectors" in plot_options and any( elm in plot_options for elm in ["vector1", "vector2", "vector3"]): warnings.warn( 'Providing new user input option "vectors" and deprecated user input options ' '"vector1", "vector2" and "vector3" simultaneously. Initially selected vectors ' 'for plugin are set equal to new user input option "vectors".') if not initial_vectors: initial_vectors = [ plot_options[elm] for elm in ["vector1", "vector2", "vector3"] if elm in plot_options ][:3] # Check if initially selected vectors exist in data, raise ValueError if not missing_vectors = [ elm for elm in initial_vectors if not is_vector_name_in_vector_selector_data( elm, self._initial_vector_selector_data) ] if missing_vectors: raise ValueError( f"Cannot find: {', '.join(missing_vectors)} to plot initially in " "SimulationTimeSeries. Check that the vector(s) exist in your data." ) if len(initial_vectors) > 3: warnings.warn( 'User input option "vectors" contains more than 3 vectors. Only the first 3 listed ' "vectors are kept for initially selected vectors - the remaining are neglected." ) self._initial_vectors = initial_vectors[:3] # Set callbacks self.set_callbacks(app)
def create_vector_plot_titles_from_provider_set( vector_names: List[str], expressions: List[ExpressionInfo], provider_set: ProviderSet, user_defined_vector_definitions: Dict[str, VectorDefinition], resampling_frequency: Optional[Frequency] = None, ) -> Dict[str, str]: """Create plot titles for vectors Create plot titles for vectors by use of provider set metadata and list of calculation expressions `Return:` * Dictionary with vector names as keys and the corresponding title as value """ vector_title_dict: Dict[str, str] = {} all_vector_names = provider_set.all_vector_names() for vector_name in vector_names: # Provider vector if vector_name in all_vector_names: metadata = provider_set.vector_metadata(vector_name) title = simulation_vector_description( vector_name, user_defined_vector_definitions) if metadata and metadata.unit: title += f" [{simulation_unit_reformat(metadata.unit)}]" vector_title_dict[vector_name] = title # Per Interval or Per Day vector elif is_per_interval_or_per_day_vector(vector_name): title = simulation_vector_description( vector_name, user_defined_vector_definitions) cumulative_vector = get_cumulative_vector_name(vector_name) metadata = provider_set.vector_metadata(cumulative_vector) if resampling_frequency: title = f"{str(resampling_frequency.value).capitalize()} " + title if vector_name.startswith("PER_DAY_"): if metadata and metadata.unit: _unit = metadata.unit + "/DAY" title += f" [{simulation_unit_reformat(_unit)}]" if vector_name.startswith("PER_INTVL_"): if metadata and metadata.unit: title += f" [{simulation_unit_reformat(metadata.unit)}]" vector_title_dict[vector_name] = title # Calculated vector else: expression = get_expression_from_name(vector_name, expressions) if expression: unit = create_calculated_unit_from_provider_set( expression, provider_set) if unit: # TODO: Expression description instead of vector name in title? vector_title_dict[vector_name] = f"{vector_name} [{unit}]" else: vector_title_dict[vector_name] = vector_name else: vector_title_dict[vector_name] = vector_name return vector_title_dict
def eclipse_vector_description(keyword): return UDF_VECTOR.get(keyword, simulation_vector_description(keyword))
def __init__( self, app, x_axis=None, y_axis=None, ensembles=None, reference_cases=None, column_keys=None, krpc_ensembles=None, ensembles_idx=None, krpc_references=None, ): super().__init__() # Get setting from shared_settings shared_settings = app.webviz_settings["shared_settings"] self.plot_profile = ensembles or reference_cases self.plot_krpc = krpc_ensembles or krpc_references self.plot_ensembles = ensembles or krpc_ensembles self.plot_references = reference_cases or krpc_references self.x_axis = x_axis self.y_axis = [] if y_axis is None else y_axis self.column_keys = column_keys self.krpc_csv_tables = None self.references_tuple = () self.case_tuple = () self.ensemble_paths = () self.colors = PALETTE["tableau"] if not (self.plot_profile or self.plot_krpc): raise ValueError( "Nothing to visualize.\n Please specify at least one Eclipse case or krpc table" ) keywords = [] if self.plot_profile: if ensembles is None: self.ensemble_paths = () self.df_ens = None else: self.ensemble_paths = tuple( (ensemble, shared_settings["scratch_ensembles"][ensemble]) for ensemble in ensembles) self.df_ens = get_ensemble_df(self.ensemble_paths, self.column_keys) keywords.extend(self.df_ens.columns) if reference_cases is None: warning( "[UpCaRs Container] User didn't specify any reference cases" ) self.df_ref = None else: self.references_tuple = tuple( (reference, shared_settings["realizations"][reference]) for reference in reference_cases) self.df_ref = get_summary_df(self.references_tuple, self.column_keys) keywords.extend(self.df_ref.columns) # Get all columns keywords.remove("REAL") keywords.remove("ENSEMBLE") keywords = sorted(list(set(keywords))) self.keywords_options = [{ "label": "{} ({})".format( UDF_VECTOR.get(val, simulation_vector_description(val)), val), "value": val, } for val in keywords] if x_axis in keywords: self.x_axis = x_axis else: self.x_axis = keywords[0] self.y_axis = [key for key in y_axis if key in keywords] else: self.keywords_options = [] self.x_axis = None self.y_axis = [] if self.plot_krpc: if krpc_references: self.case_tuple = tuple( (case, shared_settings["krpc_csv_tables"][case]) for case in krpc_references) self.df_ref_krpc = get_multiple_table_df(self.case_tuple)
def __init__( self, app: dash.Dash, webviz_settings: WebvizSettings, ensembles: Optional[list] = None, rel_file_pattern: str = "share/results/unsmry/*.arrow", perform_presampling: bool = False, obsfile: Path = None, options: dict = None, sampling: str = Frequency.MONTHLY.value, predefined_expressions: str = None, line_shape_fallback: str = "linear", ) -> None: super().__init__() # NOTE: 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") self._webviz_settings = webviz_settings self._obsfile = obsfile self._line_shape_fallback = set_simulation_line_shape_fallback( line_shape_fallback) # Must define valid freqency! if Frequency.from_string_value(sampling) is None: raise ValueError( 'Sampling frequency conversion is "None", i.e. Raw sampling, and ' "is not supported by plugin yet!") self._sampling = Frequency(sampling) self._presampled_frequency = None # TODO: Update functionality when allowing raw data and csv file input # NOTE: If csv is implemented-> handle/disable statistics, INTVL_, AVG_, delta # ensemble, etc. if ensembles is not None: ensemble_paths: Dict[str, Path] = { ensemble_name: webviz_settings.shared_settings["scratch_ensembles"] [ensemble_name] for ensemble_name in ensembles } if perform_presampling: self._presampled_frequency = self._sampling self._input_provider_set = create_presampled_provider_set_from_paths( ensemble_paths, rel_file_pattern, self._presampled_frequency) else: self._input_provider_set = create_lazy_provider_set_from_paths( ensemble_paths, rel_file_pattern) else: raise ValueError('Incorrect argument, must provide "ensembles"') if not self._input_provider_set: raise ValueError( "Initial provider set is undefined, and ensemble summary providers" " are not instanciated for plugin") self._theme = webviz_settings.theme self._observations = {} if self._obsfile: self._observations = check_and_format_observations( get_path(self._obsfile)) # NOTE: Initially keep set of all vector names - can make dynamic if wanted? vector_names = self._input_provider_set.all_vector_names() non_historical_vector_names = [ vector for vector in vector_names if historical_vector(vector, None, False) not in vector_names ] # NOTE: Initially: With set of vector names, the vector selector data is static # Can be made dynamic based on selected ensembles - i.e. vectors present among # selected providers? self._vector_selector_base_data: list = [] self._vector_calculator_data: list = [] for vector in non_historical_vector_names: split = vector.split(":") add_vector_to_vector_selector_data( self._vector_selector_base_data, vector, simulation_vector_description(split[0]), ) add_vector_to_vector_selector_data( self._vector_calculator_data, vector, simulation_vector_description(split[0]), ) metadata = (self._input_provider_set.vector_metadata(vector) if self._input_provider_set else None) if metadata and metadata.is_total: # Get the likely name for equivalent rate vector and make dropdown options. # Requires that the time_index was either defined or possible to infer. avgrate_vec = rename_vector_from_cumulative(vector=vector, as_rate=True) interval_vec = rename_vector_from_cumulative(vector=vector, as_rate=False) avgrate_split = avgrate_vec.split(":") interval_split = interval_vec.split(":") add_vector_to_vector_selector_data( self._vector_selector_base_data, avgrate_vec, f"{simulation_vector_description(avgrate_split[0])} ({avgrate_vec})", ) add_vector_to_vector_selector_data( self._vector_selector_base_data, interval_vec, f"{simulation_vector_description(interval_split[0])} ({interval_vec})", ) # Retreive predefined expressions from configuration and validate self._predefined_expressions_path = ( None if predefined_expressions is None else webviz_settings. shared_settings["predefined_expressions"][predefined_expressions]) self._predefined_expressions = expressions_from_config( get_path(self._predefined_expressions_path) if self. _predefined_expressions_path else None) for expression in self._predefined_expressions: valid, message = validate_predefined_expression( expression, self._vector_selector_base_data) if not valid: warnings.warn(message) expression["isValid"] = valid # Create initial vector selector data with predefined expressions self._initial_vector_selector_data = copy.deepcopy( self._vector_selector_base_data) add_expressions_to_vector_selector_data( self._initial_vector_selector_data, self._predefined_expressions) plot_options = options if options else {} self._initial_visualization_selection = VisualizationOptions( plot_options.get("visualization", "statistics")) self._initial_vectors: List[str] = [] if "vectors" not in plot_options: self._initial_vectors = [] for vector in [ vector for vector in ["vector1", "vector2", "vector3"] if vector in plot_options ]: self._initial_vectors.append(plot_options[vector]) self._initial_vectors = self._initial_vectors[:3] # Set callbacks self.set_callbacks(app)