def __init__( self, app, webviz_settings: WebvizSettings, ensembles: Optional[list] = None, csvfile_parameters: pathlib.Path = None, csvfile_smry: pathlib.Path = None, time_index: str = "monthly", column_keys: Optional[list] = None, drop_constants: bool = True, ): super().__init__() self.theme = webviz_settings.theme self.time_index = time_index self.column_keys = column_keys self.ensembles = ensembles self.csvfile_parameters = csvfile_parameters self.csvfile_smry = csvfile_smry if ensembles is not None: self.emodel: EnsembleSetModel = ( caching_ensemble_set_model_factory.get_or_create_model( ensemble_paths={ ens: webviz_settings.shared_settings["scratch_ensembles"] [ens] for ens in ensembles }, time_index=self.time_index, column_keys=self.column_keys, )) self.pmodel = ParametersModel( dataframe=self.emodel.load_parameters(), theme=self.theme, drop_constants=drop_constants, ) self.vmodel = SimulationTimeSeriesModel( dataframe=self.emodel.get_or_load_smry_cached()) elif self.csvfile_parameters is None: raise ValueError( "Either ensembles or csvfile_parameters must be specified") else: self.pmodel = ParametersModel( dataframe=read_csv(csvfile_parameters), theme=self.theme, drop_constants=drop_constants, ) if self.csvfile_smry is not None: self.vmodel = SimulationTimeSeriesModel( dataframe=read_csv(csvfile_smry)) else: self.vmodel = None self._parameter_filter = ParameterFilter(app, self.uuid("parameter-filter"), self.pmodel.dataframe) self.set_callbacks(app)
def __init__( self, app: Dash, webviz_settings: WebvizSettings, ensembles: list, wells: Optional[List[str]] = None, ): super().__init__() if wells is None: self.column_keys = ["WBHP:*"] else: self.column_keys = [f"WBHP:{well}" for well in wells] self.emodel: EnsembleSetModel = ( caching_ensemble_set_model_factory.get_or_create_model( ensemble_paths={ ens: webviz_settings.shared_settings["scratch_ensembles"][ens] for ens in ensembles }, time_index="raw", column_keys=self.column_keys, )) self.smry = self.emodel.get_or_load_smry_cached() self.theme = webviz_settings.theme self.set_callbacks(app)
def __init__( self, app: dash.Dash, webviz_settings: WebvizSettings, ensembles: Optional[list] = None, statistics_file: str = "share/results/tables/gridpropstatistics.csv", csvfile_statistics: pathlib.Path = None, csvfile_smry: pathlib.Path = None, surface_renaming: Optional[dict] = None, time_index: str = "monthly", column_keys: Optional[list] = None, ): super().__init__() WEBVIZ_ASSETS.add( pathlib.Path(webviz_subsurface.__file__).parent / "_assets" / "css" / "container.css") self.theme: WebvizConfigTheme = webviz_settings.theme self.time_index = time_index self.column_keys = column_keys self.statistics_file = statistics_file self.ensembles = ensembles self.csvfile_statistics = csvfile_statistics self.csvfile_smry = csvfile_smry self.surface_folders: Union[dict, None] if ensembles is not None: self.emodel: EnsembleSetModel = ( caching_ensemble_set_model_factory.get_or_create_model( ensemble_paths={ ens: webviz_settings.shared_settings["scratch_ensembles"] [ens] for ens in ensembles }, time_index=self.time_index, column_keys=self.column_keys, )) self.pmodel = PropertyStatisticsModel( dataframe=self.emodel.load_csv( csv_file=pathlib.Path(self.statistics_file)), theme=self.theme, ) self.vmodel = SimulationTimeSeriesModel( dataframe=self.emodel.get_or_load_smry_cached(), theme=self.theme, ) self.surface_folders = { ens: folder / "share" / "results" / "maps" / ens for ens, folder in self.emodel.ens_folders.items() } else: self.pmodel = PropertyStatisticsModel( dataframe=read_csv(csvfile_statistics), theme=self.theme) self.vmodel = SimulationTimeSeriesModel( dataframe=read_csv(csvfile_smry), theme=self.theme) self.surface_folders = None self.surface_renaming = surface_renaming if surface_renaming else {} self.set_callbacks(app)
def __init__( self, app: dash.Dash, webviz_settings: WebvizSettings, csvfile_vol: Path = None, csvfile_parameters: Path = None, ensembles: list = None, volfiles: dict = None, volfolder: str = "share/results/volumes", non_net_facies: Optional[List[str]] = None, ): super().__init__() WEBVIZ_ASSETS.add( Path(webviz_subsurface.__file__).parent / "_assets" / "css" / "container.css") WEBVIZ_ASSETS.add( Path(webviz_subsurface.__file__).parent / "_assets" / "css" / "inplace_volumes.css") self.csvfile_vol = csvfile_vol self.csvfile_parameters = csvfile_parameters self.volfiles = volfiles self.volfolder = volfolder if csvfile_vol and ensembles: raise ValueError( 'Incorrent arguments. Either provide a "csvfile" or "ensembles" and "volfiles"' ) if csvfile_vol: volumes_table = read_csv(csvfile_vol) parameters: Optional[pd.DataFrame] = ( read_csv(csvfile_parameters) if csvfile_parameters else None) elif ensembles and volfiles: ensemble_paths = { ens: webviz_settings.shared_settings["scratch_ensembles"][ens] for ens in ensembles } self.emodel: EnsembleSetModel = ( caching_ensemble_set_model_factory.get_or_create_model( ensemble_paths=ensemble_paths, )) parameters = self.emodel.load_parameters() volumes_table = extract_volumes(self.emodel, volfolder, volfiles) else: raise ValueError( 'Incorrent arguments. Either provide a "csvfile" or "ensembles" and "volfiles"' ) self.volmodel = InplaceVolumesModel( volumes_table=volumes_table, parameter_table=parameters, non_net_facies=non_net_facies, ) self.theme = webviz_settings.theme self.set_callbacks(app)
def __init__( self, app: Dash, webviz_settings: WebvizSettings, csvfile_smry: Path = None, csvfile_parameters: Path = None, ensembles: list = None, column_keys: list = None, initial_vector: str = None, sampling: str = "monthly", line_shape_fallback: str = "linear", ) -> None: super().__init__() self.time_index = sampling self.column_keys = column_keys self.csvfile_smry = csvfile_smry self.csvfile_parameters = csvfile_parameters if csvfile_smry and ensembles: raise ValueError( 'Incorrent arguments. Either provide a "csvfile_smry" and "csvfile_parameters" or ' '"ensembles"') if csvfile_smry and csvfile_parameters: self.smry = read_csv(csvfile_smry) self.parameters = read_csv(csvfile_parameters) self.parameters["SENSTYPE"] = self.parameters.apply( lambda row: find_sens_type(row.SENSCASE), axis=1) self.smry_meta = None elif ensembles: self.ens_paths = { ensemble: webviz_settings.shared_settings["scratch_ensembles"][ensemble] for ensemble in ensembles } self.emodel: EnsembleSetModel = ( caching_ensemble_set_model_factory.get_or_create_model( ensemble_paths=self.ens_paths, time_index=self.time_index, column_keys=self.column_keys, )) self.smry = self.emodel.get_or_load_smry_cached() self.smry_meta = self.emodel.load_smry_meta() # Extract realizations and sensitivity information self.parameters = get_realizations(ensemble_paths=self.ens_paths, ensemble_set_name="EnsembleSet") else: raise ValueError( 'Incorrent arguments. Either provide a "csvfile_smry" and "csvfile_parameters" or ' '"ensembles"') self.smry_cols = [ c for c in self.smry.columns if c not in ReservoirSimulationTimeSeriesOneByOne.ENSEMBLE_COLUMNS and historical_vector(c, self.smry_meta, False) not in self.smry.columns ] self.initial_vector = (initial_vector if initial_vector and initial_vector in self.smry_cols else self.smry_cols[0]) self.ensembles = list(self.parameters["ENSEMBLE"].unique()) self.line_shape_fallback = set_simulation_line_shape_fallback( line_shape_fallback) self.tornadoplot = TornadoWidget(app, webviz_settings, self.parameters, allow_click=True) self.uid = uuid4() self.theme = webviz_settings.theme self.set_callbacks(app)
def __init__( self, app, webviz_settings: WebvizSettings, parameter_csv: Path = None, response_csv: Path = None, ensembles: list = None, response_file: str = None, response_filters: dict = None, response_ignore: list = None, response_include: list = None, column_keys: list = None, sampling: str = "monthly", aggregation: str = "sum", corr_method: str = "pearson", ): super().__init__() self.parameter_csv = parameter_csv if parameter_csv else None self.response_csv = response_csv if response_csv else None self.response_file = response_file if response_file else None self.response_filters = response_filters if response_filters else {} self.column_keys = column_keys self.time_index = sampling self.corr_method = corr_method self.aggregation = aggregation if response_ignore and response_include: raise ValueError( 'Incorrent argument. either provide "response_include", ' '"response_ignore" or neither') if parameter_csv and response_csv: if ensembles or response_file: raise ValueError( 'Incorrect arguments. Either provide "csv files" or ' '"ensembles and response_file".') self.parameterdf = read_csv(self.parameter_csv) self.responsedf = read_csv(self.response_csv) elif ensembles: self.ens_paths = { ens: webviz_settings.shared_settings["scratch_ensembles"][ens] for ens in ensembles } self.parameterdf = load_parameters(ensemble_paths=self.ens_paths, ensemble_set_name="EnsembleSet") if self.response_file: self.responsedf = load_csv( ensemble_paths=self.ens_paths, csv_file=response_file, ensemble_set_name="EnsembleSet", ) else: self.emodel: EnsembleSetModel = ( caching_ensemble_set_model_factory.get_or_create_model( ensemble_paths=self.ens_paths, column_keys=self.column_keys, time_index=self.time_index, )) self.responsedf = self.emodel.get_or_load_smry_cached() self.response_filters["DATE"] = "single" else: raise ValueError( 'Incorrect arguments. Either provide "csv files" or "ensembles and response_file".' ) parresp.check_runs(self.parameterdf, self.responsedf) parresp.check_response_filters(self.responsedf, self.response_filters) # Only select numerical responses self.response_columns = parresp.filter_numerical_columns( df=self.responsedf, column_ignore=response_ignore, column_include=response_include, filter_columns=self.response_filters.keys(), ) # Only select numerical parameters self.parameter_columns = parresp.filter_numerical_columns( df=self.parameterdf) self.theme = webviz_settings.theme self.set_callbacks(app)
def __init__( self, app: Dash, webviz_settings: WebvizSettings, ensembles: Optional[list] = None, rel_file_pattern: str = "share/results/unsmry/*.arrow", statistics_file: str = "share/results/tables/gridpropstatistics.csv", surface_renaming: Optional[dict] = None, time_index: str = "monthly", column_keys: Optional[list] = None, csvfile_statistics: Path = None, csvfile_smry: Path = None, ): super().__init__() self.theme: WebvizConfigTheme = webviz_settings.theme self.ensembles = ensembles self._surface_folders: Union[dict, None] = None self._vmodel: Optional[Union[SimulationTimeSeriesModel, ProviderTimeSeriesDataModel]] = None run_mode_portable = WEBVIZ_INSTANCE_INFO.run_mode == WebvizRunMode.PORTABLE table_provider = EnsembleTableProviderFactory.instance() if ensembles is not None: ensemble_paths = { ensemble_name: webviz_settings.shared_settings["scratch_ensembles"] [ensemble_name] for ensemble_name in ensembles } resampling_frequency = Frequency(time_index) provider_factory = EnsembleSummaryProviderFactory.instance() try: provider_set = { ens: provider_factory.create_from_arrow_unsmry_presampled( str(ens_path), rel_file_pattern, resampling_frequency) for ens, ens_path in ensemble_paths.items() } self._vmodel = ProviderTimeSeriesDataModel( provider_set=provider_set, column_keys=column_keys) property_df = create_df_from_table_provider( table_provider. create_provider_set_from_per_realization_csv_file( ensemble_paths, statistics_file)) except ValueError as error: message = ( f"Some/all ensembles are missing arrow files at {rel_file_pattern}.\n" "If no arrow files have been generated with `ERT` using `ECL2CSV`, " "the commandline tool `smry2arrow_batch` can be used to generate arrow " "files for an ensemble") if not run_mode_portable: raise ValueError(message) from error # NOTE: this part below is to ensure backwards compatibility for portable app's # created before the arrow support. It should be removed in the future. emodel: EnsembleSetModel = ( caching_ensemble_set_model_factory.get_or_create_model( ensemble_paths=ensemble_paths, time_index=time_index, column_keys=column_keys, )) self._vmodel = SimulationTimeSeriesModel( dataframe=emodel.get_or_load_smry_cached()) property_df = emodel.load_csv(csv_file=Path(statistics_file)) self._surface_folders = { ens: Path(ens_path.split("realization")[0]) / "share/results/maps" / ens for ens, ens_path in ensemble_paths.items() } else: if csvfile_statistics is None: raise ValueError( "If not 'ensembles', then csvfile_statistics must be provided" ) # NOTE: the try/except is for backwards compatibility with existing portable app's. # It should be removed in the future together with the support of aggregated csv-files try: property_df = create_df_from_table_provider( table_provider. create_provider_set_from_aggregated_csv_file( csvfile_statistics)) except FileNotFoundError: if not run_mode_portable: raise property_df = read_csv(csvfile_statistics) if csvfile_smry is not None: try: smry_df = create_df_from_table_provider( table_provider. create_provider_set_from_aggregated_csv_file( csvfile_smry)) except FileNotFoundError: if not run_mode_portable: raise smry_df = read_csv(csvfile_smry) self._vmodel = SimulationTimeSeriesModel(dataframe=smry_df) self._pmodel = PropertyStatisticsModel(dataframe=property_df, theme=self.theme) self._surface_renaming = surface_renaming if surface_renaming else {} self._surface_table = generate_surface_table( statistics_dframe=self._pmodel.dataframe, ensembles=self._pmodel.ensembles, surface_folders=self._surface_folders, surface_renaming=self._surface_renaming, ) self.set_callbacks(app)
def __init__( self, app, webviz_settings: WebvizSettings, ensembles: list = None, parameter_csv: Path = None, response_csv: Path = None, response_file: str = None, response_filters: dict = None, response_ignore: list = None, response_include: list = None, parameter_ignore: list = None, column_keys: list = None, sampling: str = "monthly", aggregation: str = "sum", no_responses=False, ): super().__init__() self.parameter_csv = parameter_csv if parameter_csv else None self.response_csv = response_csv if response_csv else None self.response_file = response_file if response_file else None self.response_filters = response_filters if response_filters else {} self.column_keys = column_keys self.time_index = sampling self.aggregation = aggregation self.no_responses = no_responses self.response_columns = [] if response_ignore and response_include: raise ValueError( 'Incorrent argument. Either provide "response_include", ' '"response_ignore" or neither') if parameter_csv: if ensembles or response_file: raise ValueError( 'Incorrect arguments. Either provide "parameter_csv" or ' '"ensembles and/or response_file".') if not self.no_responses: if self.response_csv: self.responsedf = read_csv(self.response_csv) else: raise ValueError( "Incorrect arguments. Missing response_csv.") self.parameterdf = read_csv(self.parameter_csv) elif ensembles: if self.response_csv: raise ValueError( 'Incorrect arguments. Either provide "response_csv" or ' '"ensembles and/or response_file".') self.emodel: EnsembleSetModel = ( caching_ensemble_set_model_factory.get_or_create_model( ensemble_paths={ ens: webviz_settings.shared_settings["scratch_ensembles"] [ens] for ens in ensembles }, time_index=self.time_index, column_keys=self.column_keys, )) self.parameterdf = self.emodel.load_parameters() if not self.no_responses: if self.response_file: self.responsedf = self.emodel.load_csv( csv_file=response_file) else: self.responsedf = self.emodel.get_or_load_smry_cached() self.response_filters["DATE"] = "single" else: raise ValueError( "Incorrect arguments." 'You have to define at least "ensembles" or "parameter_csv".') if not self.no_responses: parresp.check_runs(parameterdf=self.parameterdf, responsedf=self.responsedf) parresp.check_response_filters( responsedf=self.responsedf, response_filters=self.response_filters) # only select numerical responses self.response_columns = parresp.filter_numerical_columns( df=self.responsedf, column_ignore=response_ignore, column_include=response_include, filter_columns=self.response_filters.keys(), ) # Only select numerical parameters self.parameter_columns = parresp.filter_numerical_columns( df=self.parameterdf, column_ignore=parameter_ignore) self.theme = webviz_settings.theme self.set_callbacks(app)
def __init__( self, app: dash.Dash, webviz_settings: WebvizSettings, csvfile: Path = None, ensembles: list = None, obsfile: Path = None, column_keys: list = None, sampling: str = "monthly", options: dict = None, line_shape_fallback: str = "linear", ): super().__init__() self.csvfile = csvfile self.obsfile = obsfile self.time_index = sampling self.column_keys = column_keys if csvfile and ensembles: raise ValueError( 'Incorrent arguments. Either provide a "csvfile" or "ensembles"' ) self.observations = {} if obsfile: self.observations = check_and_format_observations( get_path(self.obsfile)) self.smry: pd.DataFrame self.smry_meta: Union[pd.DataFrame, None] if csvfile: self.smry = read_csv(csvfile) self.smry_meta = None # Check of time_index for data to use in resampling. Quite naive as it only checks for # unique values of the DATE column, and not per realization. # # Currently not necessary as we don't allow resampling for average rates and intervals # unless we have metadata, which csvfile input currently doesn't support. # See: https://github.com/equinor/webviz-subsurface/issues/402 self.time_index = pd.infer_freq( sorted(pd.to_datetime(self.smry["DATE"]).unique())) elif ensembles: self.emodel: EnsembleSetModel = ( caching_ensemble_set_model_factory.get_or_create_model( ensemble_paths={ ens: webviz_settings.shared_settings["scratch_ensembles"] [ens] for ens in ensembles }, time_index=self.time_index, column_keys=self.column_keys, )) self.smry = self.emodel.get_or_load_smry_cached() self.smry_meta = self.emodel.load_smry_meta() else: raise ValueError( 'Incorrent arguments. Either provide a "csvfile" or "ensembles"' ) if any( col.startswith(("AVG_", "INTVL_")) for col in self.smry.columns): raise ValueError( "Your data set includes time series vectors which have names starting with" "'AVG_' and/or 'INTVL_'. These prefixes are not allowed, as they are used" "internally in the plugin.") self.smry_cols = [ c for c in self.smry.columns if c not in ReservoirSimulationTimeSeries.ENSEMBLE_COLUMNS and not historical_vector(c, self.smry_meta, False) in self.smry.columns ] self.dropdown_options = [] for vec in self.smry_cols: self.dropdown_options.append({ "label": f"{simulation_vector_description(vec)} ({vec})", "value": vec }) if (self.smry_meta is not None and self.smry_meta.is_total[vec] and self.time_index is not None): # 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_vec_from_cum(vector=vec, as_rate=True) interval_vec = rename_vec_from_cum(vector=vec, as_rate=False) self.dropdown_options.append({ "label": f"{simulation_vector_description(avgrate_vec)} ({avgrate_vec})", "value": avgrate_vec, }) self.dropdown_options.append({ "label": f"{simulation_vector_description(interval_vec)} ({interval_vec})", "value": interval_vec, }) self.ensembles = list(self.smry["ENSEMBLE"].unique()) self.theme = webviz_settings.theme self.plot_options = options if options else {} self.plot_options["date"] = (str(self.plot_options.get("date")) if self.plot_options.get("date") else None) self.line_shape_fallback = set_simulation_line_shape_fallback( line_shape_fallback) # Check if initially plotted vectors exist in data, raise ValueError if not. missing_vectors = [ value for key, value in self.plot_options.items() if key in ["vector1", "vector2", "vector3"] and value not in self.smry_cols ] if missing_vectors: raise ValueError( f"Cannot find: {', '.join(missing_vectors)} to plot initially in " "ReservoirSimulationTimeSeries. Check that the vectors exist in your data, and " "that they are not missing in a non-default column_keys list in the yaml config " "file.") self.allow_delta = len(self.ensembles) > 1 self.set_callbacks(app)
def __init__( self, webviz_settings: WebvizSettings, ensembles: Optional[List[str]], formations: Path = None, faultlines: Path = None, obsdata: Path = None, csvfile_rft: Path = None, csvfile_rft_ert: Path = None, ): self.formations = formations self.faultlines = faultlines self.obsdata = obsdata self.csvfile_rft = csvfile_rft self.csvfile_rft_ert = csvfile_rft_ert if csvfile_rft_ert and ensembles: raise ValueError( 'Incorrent arguments. Either provide a "csvfile_rft_ert" or "ensembles"' ) self.simdf = read_csv( self.csvfile_rft) if csvfile_rft is not None else None self.formationdf = read_csv( self.formations) if self.formations else None self.faultlinesdf = read_csv( self.faultlines) if self.faultlines else None self.obsdatadf = read_csv(self.obsdata) if self.obsdata else None self.ertdatadf = pd.DataFrame() if csvfile_rft_ert is not None: self.ertdatadf = read_csv(self.csvfile_rft_ert) self.param_model = ParametersModel(pd.DataFrame()) if ensembles is not None: ens_paths = { ens: webviz_settings.shared_settings["scratch_ensembles"][ens] for ens in ensembles } self.emodel: EnsembleSetModel = ( caching_ensemble_set_model_factory.get_or_create_model( ensemble_paths=ens_paths, )) try: self.simdf = self.emodel.load_csv( Path("share/results/tables/rft.csv")) except (KeyError, OSError): self.simdf = None self.param_model = ParametersModel( dataframe=self.emodel.load_parameters(), drop_constants=True, keep_numeric_only=True, ) try: self.ertdatadf = self.emodel.load_csv( Path("share/results/tables/rft_ert.csv")) except KeyError as exc: raise KeyError( "CSV file for ERT RFT observations/simulations " "(share/results/tables/rft_ert.csv) not found!") from exc self.ertdatadf = self.ertdatadf.rename( columns={ "time": "DATE", "is_active": "ACTIVE", "isactive": "ACTIVE", "well": "WELL", "zone": "ZONE", "pressure": "SIMULATED", "true_vertical_depth": "TVD", "measured_depth": "MD", "observed": "OBSERVED", "obs": "OBSERVED", "error": "OBSERVED_ERR", "utm_x": "EAST", "utm_y": "NORTH", }) self.ertdatadf["DIFF"] = (self.ertdatadf["SIMULATED"] - self.ertdatadf["OBSERVED"]) self.ertdatadf["ABSDIFF"] = abs(self.ertdatadf["SIMULATED"] - self.ertdatadf["OBSERVED"]) self.ertdatadf["YEAR"] = pd.to_datetime(self.ertdatadf["DATE"]).dt.year self.ertdatadf = self.ertdatadf.sort_values(by="DATE") self.ertdatadf["DATE_IDX"] = self.ertdatadf["DATE"].apply( lambda x: list(self.ertdatadf["DATE"].unique()).index(x)) self.date_marks = self.set_date_marks() self.ertdatadf = filter_frame( self.ertdatadf, { "ACTIVE": 1, }, ) self.ertdatadf["STDDEV"] = self.ertdatadf.groupby( ["WELL", "DATE", "ZONE", "ENSEMBLE", "TVD"])["SIMULATED"].transform("std")