Skip to content

Commit

Permalink
Merge branch 'master' into volanalysis_store_bug
Browse files Browse the repository at this point in the history
  • Loading branch information
asnyv authored Jan 18, 2022
2 parents d0c14e0 + 10b792b commit 9cd0636
Show file tree
Hide file tree
Showing 110 changed files with 7,274 additions and 1,439 deletions.
2 changes: 0 additions & 2 deletions .github/CODEOWNERS

This file was deleted.

5 changes: 5 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
[MASTER]

# As a temporary workaround for https://github.com/PyCQA/pylint/issues/4577
init-hook = "import astroid; astroid.context.InferenceContext.max_inferred = 500"

[MESSAGES CONTROL]

disable = bad-continuation, missing-docstring, duplicate-code, logging-fstring-interpolation, unspecified-encoding
Expand Down
105 changes: 91 additions & 14 deletions CHANGELOG.md

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"RftPlotter = webviz_subsurface.plugins:RftPlotter",
"RunningTimeAnalysisFMU = webviz_subsurface.plugins:RunningTimeAnalysisFMU",
"SegyViewer = webviz_subsurface.plugins:SegyViewer",
"SimulationTimeSeries = webviz_subsurface.plugins:SimulationTimeSeries",
"SeismicMisfit = webviz_subsurface.plugins:SeismicMisfit",
"StructuralUncertainty = webviz_subsurface.plugins:StructuralUncertainty",
"SubsurfaceMap = webviz_subsurface.plugins:SubsurfaceMap",
Expand Down Expand Up @@ -93,9 +94,9 @@
"pyscal>=0.7.5",
"scipy>=1.2",
"statsmodels>=0.12.1", # indirect dependency through https://plotly.com/python/linear-fits/
"webviz-config>=0.3.1",
"webviz-config>=0.3.8",
"webviz-core-components>=0.5.1",
"webviz-subsurface-components>=0.4.7",
"webviz-subsurface-components>=0.4.8",
"xtgeo>=2.14",
],
extras_require={"tests": TESTS_REQUIRE},
Expand Down
17 changes: 11 additions & 6 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from webviz_config.common_cache import CACHE
from webviz_config.themes import default_theme
from webviz_config.webviz_factory_registry import WEBVIZ_FACTORY_REGISTRY
from webviz_config.webviz_instance_info import WebvizInstanceInfo, WebvizRunMode
from webviz_config.webviz_instance_info import WEBVIZ_INSTANCE_INFO, WebvizRunMode


def pytest_addoption(parser: Parser) -> None:
Expand All @@ -28,14 +28,19 @@ def testdata_folder_fixture(request: SubRequest) -> Any:

@pytest.fixture()
def app() -> dash.Dash:
run_mode = WebvizRunMode.NON_PORTABLE
storage_folder = pathlib.Path(__file__).resolve().parent
app_instance_info = WebvizInstanceInfo(run_mode, storage_folder)
dash_app = dash.Dash(__name__)

WEBVIZ_INSTANCE_INFO.initialize(
dash_app=dash_app,
run_mode=WebvizRunMode.NON_PORTABLE,
theme=default_theme,
storage_folder=pathlib.Path(__file__).resolve().parent,
)
try:
WEBVIZ_FACTORY_REGISTRY.initialize(app_instance_info, None)
WEBVIZ_FACTORY_REGISTRY.initialize(None)
except RuntimeError:
pass
dash_app = dash.Dash(__name__)

dash_app.css.config.serve_locally = True
dash_app.scripts.config.serve_locally = True
dash_app.config.suppress_callback_exceptions = True
Expand Down
79 changes: 65 additions & 14 deletions tests/unit_tests/plugin_tests/test_grouptree.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import datetime
from pathlib import Path
from typing import List, Tuple

import pandas as pd
import pytest
from _pytest.fixtures import SubRequest

from webviz_subsurface.plugins._group_tree.group_tree_data import add_nodetype_for_ens
from webviz_subsurface._providers import EnsembleSummaryProvider
from webviz_subsurface._providers.ensemble_summary_provider._provider_impl_arrow_presampled import (
ProviderImplArrowPresampled,
)
from webviz_subsurface.plugins._group_tree._ensemble_group_tree_data import add_nodetype

ADD_NODETYPE_CASES = [
# Group leaf nodes:
# NODE1 has summary data>0 and will be classified as prod and inj
# NODE2 has summary data==0 and will be classified as other
# NODE3 has no summary data and will be classified as other
# FIELD and TMPL are classified as all three types
pytest.param(
(
pd.DataFrame(
columns=["DATE", "CHILD", "KEYWORD", "PARENT"],
data=[
Expand All @@ -23,9 +30,16 @@
],
),
pd.DataFrame(
columns=["DATE", "GGPR:NODE1", "GGIR:NODE1", "GGPR:NODE2", "GGIR:NODE2"],
columns=[
"DATE",
"REAL",
"GGPR:NODE1",
"GGIR:NODE1",
"GGPR:NODE2",
"GGIR:NODE2",
],
data=[
[datetime.date(2000, 1, 1), 1, 1, 0, 0],
[datetime.date(2000, 1, 1), 0, 1, 1, 0, 0],
],
),
pd.DataFrame(
Expand All @@ -46,7 +60,6 @@
["2000-01-01", "NODE3", "GRUPTREE", "TMPL", False, False, True],
],
),
id="add-nodetype-for-group-leaf-nodes",
),
# Well leaf nodes:
# WELL1 has WSTAT==1 and will be classified as producer
Expand All @@ -55,7 +68,7 @@
# WELL4 has WSTAT==0 and will be classified as other
# TMPL_A is classified as prod and inj
# TMPL_B is classified as other
pytest.param(
(
pd.DataFrame(
columns=["DATE", "CHILD", "KEYWORD", "PARENT"],
data=[
Expand All @@ -71,14 +84,15 @@
pd.DataFrame(
columns=[
"DATE",
"REAL",
"WSTAT:WELL1",
"WSTAT:WELL2",
"WSTAT:WELL3",
"WSTAT:WELL4",
],
data=[
[datetime.date(2000, 1, 1), 1, 2, 1, 0],
[datetime.date(2000, 2, 1), 1, 2, 2, 0],
[datetime.date(2000, 1, 1), 0, 1, 2, 1, 0],
[datetime.date(2000, 2, 1), 0, 1, 2, 2, 0],
],
),
pd.DataFrame(
Expand All @@ -101,14 +115,45 @@
["2000-01-01", "WELL4", "WELSPECS", "TMPL_B", False, False, True],
],
),
id="add-nodetype-for-well-leaf-nodes",
),
]


@pytest.mark.parametrize("gruptree, smry, expected", ADD_NODETYPE_CASES)
def test_add_nodetype(gruptree, smry, expected):
"""Test functionality of the add_nodetype_for_ens function"""
@pytest.fixture(
name="testdata",
params=ADD_NODETYPE_CASES,
)
def fixture_provider(
request: SubRequest, tmp_path: Path
) -> Tuple[pd.DataFrame, EnsembleSummaryProvider, pd.DataFrame]:

input_py = request.param
storage_dir = tmp_path
gruptree_df = input_py[0]
smry_df = input_py[1]
expected_df = input_py[2]

ProviderImplArrowPresampled.write_backing_store_from_ensemble_dataframe(
storage_dir, "dummy_key", smry_df
)
new_provider = ProviderImplArrowPresampled.from_backing_store(
storage_dir, "dummy_key"
)

if not new_provider:
raise ValueError("Failed to create EnsembleSummaryProvider")

return gruptree_df, new_provider, expected_df


def test_add_nodetype(
testdata: Tuple[pd.DataFrame, EnsembleSummaryProvider, pd.DataFrame]
) -> None:
"""Test functionality for the add_nodetype function"""
gruptree_df = testdata[0]
provider = testdata[1]
expected_df = testdata[2]

columns_to_check = [
"DATE",
"CHILD",
Expand All @@ -118,6 +163,12 @@ def test_add_nodetype(gruptree, smry, expected):
"IS_INJ",
"IS_OTHER",
]
output = add_nodetype_for_ens(gruptree, smry)

pd.testing.assert_frame_equal(output[columns_to_check], expected[columns_to_check])
wells: List[str] = gruptree_df[gruptree_df["KEYWORD"] == "WELSPECS"][
"CHILD"
].unique()

output = add_nodetype(gruptree_df, provider, wells)
pd.testing.assert_frame_equal(
output[columns_to_check], expected_df[columns_to_check]
)
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ def test_create_from_arrow_unsmry_lazy(testdata_folder: Path, tmp_path: Path) ->
# _dump_smry_to_csv_using_fmu(ensemble_path, "monthly", "expected_smry.csv")

factory = EnsembleSummaryProviderFactory(tmp_path, allow_storage_writes=True)
provider = factory.create_from_arrow_unsmry_lazy(ensemble_path)
provider = factory.create_from_arrow_unsmry_lazy(
ens_path=ensemble_path, rel_file_pattern="share/results/unsmry/*.arrow"
)

assert provider.supports_resampling()

Expand Down Expand Up @@ -100,7 +102,9 @@ def test_arrow_unsmry_lazy_vector_metadata(

ensemble_path = str(testdata_folder / "01_drogon_ahm/realization-*/iter-0")
factory = EnsembleSummaryProviderFactory(tmp_path, allow_storage_writes=True)
provider = factory.create_from_arrow_unsmry_lazy(ensemble_path)
provider = factory.create_from_arrow_unsmry_lazy(
ens_path=ensemble_path, rel_file_pattern="share/results/unsmry/*.arrow"
)

meta: Optional[VectorMetadata] = provider.vector_metadata("FOPR")
assert meta is not None
Expand Down Expand Up @@ -141,7 +145,9 @@ def test_create_from_arrow_unsmry_presampled_monthly(

factory = EnsembleSummaryProviderFactory(tmp_path, allow_storage_writes=True)
provider = factory.create_from_arrow_unsmry_presampled(
str(ensemble_path), Frequency.MONTHLY
ens_path=str(ensemble_path),
rel_file_pattern="share/results/unsmry/*.arrow",
sampling_frequency=Frequency.MONTHLY,
)

assert not provider.supports_resampling()
Expand Down
3 changes: 1 addition & 2 deletions webviz_subsurface/_assets/css/inplace_volumes.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
.webviz-inplace-vol-btn {
background-color: #E8E8E8;
width: 100%;
display: block;
margin-left: auto;
font-size: 12px;
height: 30px;
line-height:30px;
padding:0px;
}


Expand Down
2 changes: 1 addition & 1 deletion webviz_subsurface/_components/parameter_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def store_selections(n_clicks: int, range_sliders: list, selects: list) -> Dict:
real_dict[ens] = list(ens_df["REAL"].unique())

for ens in self._ensembles:
if ens not in real_dict.keys():
if ens not in real_dict:
real_dict[ens] = []
return real_dict

Expand Down
2 changes: 1 addition & 1 deletion webviz_subsurface/_datainput/seismic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

@CACHE.memoize(timeout=CACHE.TIMEOUT)
def load_cube_data(cube_path: str) -> xtgeo.Cube:
return xtgeo.Cube(cube_path)
return xtgeo.cube_from_file(cube_path)


@CACHE.memoize(timeout=CACHE.TIMEOUT)
Expand Down
6 changes: 3 additions & 3 deletions webviz_subsurface/_datainput/xsection.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from numpy import ma
from plotly.subplots import make_subplots

from .._utils.colors import hex_to_rgba
from .._utils.colors import hex_to_rgba_str


class XSectionFigure:
Expand Down Expand Up @@ -472,8 +472,8 @@ def plot_statistical_surface(
self._surfacenames.index(name) % len(self._surfacecolors) # type: ignore[union-attr]
]

fill_color = hex_to_rgba(color, 0.3)
line_color = hex_to_rgba(color, 1)
fill_color = hex_to_rgba_str(color, 0.3)
line_color = hex_to_rgba_str(color, 1)

# Extract surface values along well fence
x_values = statistical_surfaces["mean"].get_randomline(self.fence).copy()[:, 0]
Expand Down
2 changes: 2 additions & 0 deletions webviz_subsurface/_figures/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from .barchart import BarChart
from .px_figure import create_figure
from .scatterplot import ScatterPlot
92 changes: 92 additions & 0 deletions webviz_subsurface/_figures/barchart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from typing import Any, Dict, List

import pandas as pd

from .._utils.colors import hex_to_rgba_str


class BarChart:
"""General bar chart class.
Input:
* series: pandas series with values and names in the index
* n_rows: how many of the values to display
* title
* orientation
"""

def __init__(self, series: pd.Series, n_rows: int, title: str, orientation: str):
self.series = series.tail(n=n_rows)
self.title = title
self.orientation = orientation
self._data = self.initial_data

@property
def data(self) -> List[Dict[str, Any]]:
return self._data

@property
def figure(self) -> Dict[str, Any]:
return {"data": self.data, "layout": self.layout}

@property
def initial_data(self) -> List[Dict[str, Any]]:
return [
{
"x": self.series.values,
"y": self.series.index,
"orientation": self.orientation,
"type": "bar",
"marker": {},
}
]

@property
def layout(self) -> Dict[str, Any]:
return {
"title": self.title,
"margin": {
"r": 20,
"t": 60,
"b": 20,
},
"barmode": "relative",
"xaxis": {
"range": [
self.series.values.min() - 0.1,
self.series.values.max() + 0.1,
]
},
"yaxis": {"automargin": True},
}

@property
def first_y_value(self) -> str:
return self.data[0]["y"][-1]

def color_bars(
self,
selected_bar: str,
color: str,
opacity: float,
color_selected: str = "#FF1243",
) -> None:
"""
Set colors to the correlation plot bar,
with separate color for the selected bar
"""
self._data[0]["marker"] = {
"color": [
hex_to_rgba_str(color, opacity)
if _bar != selected_bar
else hex_to_rgba_str(color_selected, 0.8)
for _bar in self._data[0]["y"]
],
"line": {
"color": [
color if _bar != selected_bar else color_selected
for _bar in self._data[0]["y"]
],
"width": 1.2,
},
}
Loading

0 comments on commit 9cd0636

Please sign in to comment.