diff --git a/ertviz/controllers/__init__.py b/ertviz/controllers/__init__.py index 2fa005b0..c714adc7 100644 --- a/ertviz/controllers/__init__.py +++ b/ertviz/controllers/__init__.py @@ -1,10 +1,3 @@ -import re - - -def parse_url_query(search): - return {key: value for (key, value) in re.findall("(\w*)\=(\w*)", search)} - - from .link_and_brush_controller import link_and_brush_controller from .ensemble_selector_controller import ensemble_selector_controller from .multi_response_controller import multi_response_controller diff --git a/ertviz/controllers/observation_response_controller.py b/ertviz/controllers/observation_response_controller.py index 8ed47840..64a71bde 100644 --- a/ertviz/controllers/observation_response_controller.py +++ b/ertviz/controllers/observation_response_controller.py @@ -2,40 +2,24 @@ from dash.dependencies import Input, Output, State from dash.exceptions import PreventUpdate from copy import deepcopy -from ertviz.models import ResponsePlotModel, BoxPlotModel, PlotModel, EnsembleModel -import ertviz.assets as assets - - -def _get_univariate_misfits_plots(misfits_df, color): - if misfits_df is None: - return [] - style = deepcopy(assets.ERTSTYLE["observation-response-plot"]["misfits"]) - style["line"]["color"] = color - style["marker"]["color"] = color - x_axis = misfits_df.pop("x_axis") - misfits_data = list() - for misfits in misfits_df: - plot = PlotModel( - x_axis=x_axis, - y_axis=misfits_df[misfits].pow(1 / 2.0).values, - text=misfits, - name=misfits, - **style, - ) - misfits_data.append(plot) - return misfits_data +from ertviz.models import ( + ResponsePlotModel, + BoxPlotModel, + EnsembleModel, + MultiHistogramPlotModel, +) def _get_univariate_misfits_boxplots(misfits_df, color): if misfits_df is None: return [] + x_axis = misfits_df.pop("x_axis") misfits_data = list() for misfits in misfits_df.T: plot = BoxPlotModel( - x_axis=[x_axis.loc[misfits]], - y_axis=misfits_df.T[misfits].pow(1 / 2.0).values, - text=misfits, + x_axis=[int(x_axis[misfits])], + y_axis=misfits_df.T[misfits].values, name=f"Misfits@{int(x_axis.loc[misfits])}", color=color, ) @@ -43,36 +27,15 @@ def _get_univariate_misfits_boxplots(misfits_df, color): return misfits_data -def _get_observation_plots(observation_df, x_axis): - data = observation_df["values"] - stds = observation_df["std"] - x_axis = observation_df["x_axis"] - style = deepcopy(assets.ERTSTYLE["observation-response-plot"]["observation"]) - observation_data = PlotModel( - x_axis=x_axis, - y_axis=stds.values, - text="Observations", - name="Observations", - **style, - ) - return [observation_data] - +def _create_misfits_plot(response, selected_realizations, color): -def _create_misfits_plot(response, yaxis_type, selected_realizations, color): - - x_axis = response.axis - # realizations = _get_univariate_misfits_plots( realizations = _get_univariate_misfits_boxplots( - response.univariate_misfits_df(selected_realizations), color=color + response.univariate_misfits_df(selected_realizations), + color=color, ) - observations = [] - - # for obs in response.observations: - # observations += _get_observation_plots(obs.data_df(), x_axis) - ensemble_plot = ResponsePlotModel( realizations, - observations, + [], dict( xaxis={"title": "Index"}, yaxis={"title": "Unit TODO"}, @@ -89,12 +52,13 @@ def observation_response_controller(parent, app): [Input(parent.uuid("ensemble-selection-store"), "data")], ) def _set_response_options(selected_ensembles): - # Should either return a union of all possible responses or the other thing which I cant think of... - if not selected_ensembles: raise PreventUpdate ensemble_id, _ = selected_ensembles.popitem() - ensemble = parent.ensembles.get(ensemble_id, EnsembleModel(ref_url=ensemble_id)) + ensemble = parent.ensembles.get( + ensemble_id, + EnsembleModel(ref_url=ensemble_id, project_id=parent.project_identifier), + ) parent.ensembles[ensemble_id] = ensemble return [ { @@ -134,11 +98,29 @@ def _update_graph(response, yaxis_type, misfits_type, selected_ensembles): if response in [None, ""] or not selected_ensembles: raise PreventUpdate + if misfits_type == "Summary": + data_dict = {} + colors = {} + for ensemble_id, color in selected_ensembles.items(): + ensemble = parent.ensembles.get(ensemble_id, None) + summary_df = ensemble.responses[response].summary_misfits_df( + selection=None + ) # What about selections? + if summary_df is not None: + data_dict[parent.ensembles[ensemble_id]._name] = summary_df + colors[parent.ensembles[ensemble_id]._name] = color["color"] + if bool(data_dict): + plot = MultiHistogramPlotModel( + data_dict, + colors=colors, + hist=True, + kde=False, + ) + return plot.repr + def _generate_plot(ensemble_id, color): ensemble = parent.ensembles.get(ensemble_id, None) - plot = _create_misfits_plot( - ensemble.responses[response], yaxis_type, None, color - ) + plot = _create_misfits_plot(ensemble.responses[response], None, color) return plot response_plots = [ diff --git a/ertviz/models/plot_model.py b/ertviz/models/plot_model.py index 917d3af3..975a7f3c 100644 --- a/ertviz/models/plot_model.py +++ b/ertviz/models/plot_model.py @@ -8,22 +8,22 @@ def __init__(self, **kwargs): self.selected = True self._x_axis = kwargs["x_axis"] self._y_axis = kwargs["y_axis"] - self._text = kwargs["text"] self._name = kwargs["name"] self._color = kwargs["color"] @property def repr(self): repr_dict = dict( - # x=self._x_axis, + # x=self._x_axis, this won't work :/ + # need something else to get axis right if required y=self._y_axis, - # text=self.display_name, name=self.display_name, boxpoints="all", jitter=0.3, pointpos=-1.8, marker_color=self._color, ) + return go.Box(repr_dict) @property diff --git a/ertviz/models/realization.py b/ertviz/models/realization.py index 62fa30b5..4410c0c3 100644 --- a/ertviz/models/realization.py +++ b/ertviz/models/realization.py @@ -1,5 +1,5 @@ import pandas as pd -from ertviz.data_loader import get_data +import math class Realization: @@ -14,16 +14,22 @@ def __init__(self, realization_schema): ) def _extract_univariate_misfits(self, schema): - if bool(schema): # this account for not None and empty dict - misfits_ = list(schema.values()) - return pd.DataFrame(misfits_[0]) - return None + # this account for not None and empty dict + if not bool(schema): + return None + misfits_ = list(schema.values()) + df = pd.DataFrame(misfits_[0]) + df["value_sign"] = df[["value", "sign"]].apply( + lambda row: -1.0 * math.sqrt(row[0]) if row[1] else math.sqrt(row[0]), + axis=1, + ) + return df def _extract_summary_misfits(self, schema): - if bool(schema): - misfits_ = list(schema.values())[0] - return misfits_ - return None + if not bool(schema): + return None + misfits_ = list(schema.values())[0] + return misfits_ @property def summarized_misfits_value(self): diff --git a/ertviz/models/response.py b/ertviz/models/response.py index fb364dfb..6868cf76 100644 --- a/ertviz/models/response.py +++ b/ertviz/models/response.py @@ -44,20 +44,41 @@ def data(self): def univariate_misfits_df(self, selection=None): if selection is not None: data = { - realization.name: realization.univariate_misfits_df["value"] + realization.name: realization.univariate_misfits_df["value_sign"] for realization in self.realizations if realization.name in selection and realization.univariate_misfits_df is not None } else: data = { - realization.name: realization.univariate_misfits_df["value"] + realization.name: realization.univariate_misfits_df["value_sign"] for realization in self.realizations if realization.univariate_misfits_df is not None } if bool(data): misfits_df = pd.DataFrame(data=data) misfits_df["x_axis"] = self.observations[0].data_df()["x_axis"] + misfits_df.index.name = self.name + return misfits_df.astype("float64") + return None + + def summary_misfits_df(self, selection=None): + if bool(selection): + data = { + realization.name: [realization.summarized_misfits_value] + for realization in self.realizations + if realization.name in selection + and bool(realization.summarized_misfits_value) + } + else: + data = { + realization.name: [realization.summarized_misfits_value] + for realization in self.realizations + if bool(realization.summarized_misfits_value) + } + if bool(data): + misfits_df = pd.DataFrame(data=data) + misfits_df.index.name = self.name return misfits_df.astype("float64") return None diff --git a/ertviz/plugins/_observation_analyzer.py b/ertviz/plugins/_observation_analyzer.py index 9f84edf2..bbc6ee5d 100644 --- a/ertviz/plugins/_observation_analyzer.py +++ b/ertviz/plugins/_observation_analyzer.py @@ -8,8 +8,9 @@ class ObservationAnalyzer(WebvizPluginABC): - def __init__(self, app): + def __init__(self, app, project_identifier: str): super().__init__() + self.project_identifier = project_identifier self.ensembles = {} self.parameter_models = {} self.set_callbacks(app) diff --git a/ertviz/views/__init__.py b/ertviz/views/__init__.py index 20cc7cdd..1c6046c5 100644 --- a/ertviz/views/__init__.py +++ b/ertviz/views/__init__.py @@ -96,4 +96,4 @@ def response_obs_view(parent): ], className="ert-graph-container", ), - ] \ No newline at end of file + ]