diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 3cc7d061..2b5d2792 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -34,5 +34,7 @@ jobs: pip install -r test_requirements.txt pytest - - name: Run black - uses: psf/black@stable + - name: Run ruff + run: | + ruff check + ruff format --check diff --git a/pyproject.toml b/pyproject.toml index ac9e5b38..74a2e3da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,3 +6,42 @@ addopts = "-m 'not spe1'" markers = [ "spe1: marks tests needing results from ert model of the spe1 test case", ] + +[tool.ruff] +src = ["webviz_ert"] +line-length = 88 + +[tool.ruff.lint] +select = [ + "W", # pycodestyle + "I", # isort + "B", # flake-8-bugbear + "SIM", # flake-8-simplify + "F", # pyflakes + "PL", # pylint + "NPY", # numpy specific rules + "C4", # flake8-comprehensions +] +preview = true +ignore = ["PLW2901", # redefined-loop-name + "PLR2004", # magic-value-comparison + "PLR0915", # too-many-statements + "PLR0912", # too-many-branches + "PLR0911", # too-many-return-statements + "PLC2701", # import-private-name + "PLR6201", # literal-membership + "PLR0914", # too-many-locals + "PLR6301", # no-self-use + "PLW1641", # eq-without-hash + "PLR0904", # too-many-public-methods + "PLR1702", # too-many-nested-blocks + "PLW3201", # bad-dunder-method-name + "PLC0414", # useless-import-alias +] + +[tool.ruff.lint.extend-per-file-ignores] +"webviz_ert/models/__init__.py" = ["I"] +"webviz_ert/plugins/__init__.py" = ["I"] + +[tool.ruff.lint.pylint] +max-args = 10 diff --git a/setup.py b/setup.py index 2ef0c44a..2a883cd9 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ -from setuptools import setup, find_packages +from setuptools import find_packages, setup -with open("README.md", "r") as fh: +with open("README.md", "r", encoding="utf-8") as fh: LONG_DESCRIPTION = fh.read() setup( diff --git a/test_requirements.txt b/test_requirements.txt index 1a5496ef..2baf9d90 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -1,9 +1,9 @@ pytest pytest-mock pylint -black +ruff scipy dash[testing]>=2.5.1 selenium -urllib3<2 # RHEL7 does not support urllib >= 2.0 +urllib3 flask>=2.2.5 # not directly required, pinned by Snyk to avoid a vulnerability diff --git a/tests/conftest.py b/tests/conftest.py index ee0c1706..002d256a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,8 +1,10 @@ +import contextlib + +import dash import pytest from requests import HTTPError -import dash -from selenium.webdriver.chrome.options import Options from selenium.common.exceptions import TimeoutException +from selenium.webdriver.chrome.options import Options from tests.data.snake_oil_data import ensembles_response @@ -200,10 +202,8 @@ def select_parameter(dash_duo, plugin, parameter_name=None, wait_for_plot=True) def wait_a_bit(dash_duo, time_seconds=0.1): - try: + with contextlib.suppress(TimeoutException): dash_duo.wait_for_element(".foo-elderberries-baarrrrr", timeout=time_seconds) - except TimeoutException: - pass def verify_key_in_dropdown(dash_duo, selector, key): diff --git a/tests/controllers/test_controller_functions.py b/tests/controllers/test_controller_functions.py index da83421a..fc24ed61 100644 --- a/tests/controllers/test_controller_functions.py +++ b/tests/controllers/test_controller_functions.py @@ -1,8 +1,8 @@ -from webviz_ert.models.ensemble_model import EnsembleModel from webviz_ert.controllers.controller_functions import ( - response_options, _valid_response_option, + response_options, ) +from webviz_ert.models.ensemble_model import EnsembleModel def test_response_options(mock_data): diff --git a/tests/controllers/test_response_correlation_controller.py b/tests/controllers/test_response_correlation_controller.py index b9fadafa..36f850f4 100644 --- a/tests/controllers/test_response_correlation_controller.py +++ b/tests/controllers/test_response_correlation_controller.py @@ -1,20 +1,15 @@ import pandas as pd import pytest - from webviz_ert.controllers.response_correlation_controller import ( _define_style_ensemble, - _layout_figure, - _format_index_value, _format_index_text, -) - -from webviz_ert.controllers.response_correlation_controller import ( - _sort_dataframe, + _format_index_value, _get_selected_indexes, + _layout_figure, + _sort_dataframe, ) from webviz_ert.models import PlotModel - PLOT_STYLE = { "mode": "markers", "line": None, @@ -141,7 +136,7 @@ def test_format_index_value(raw_value: str, expected_formatted_value: str): x_axis=[pd.Timestamp("2020-01-02")], y_axis=[1, 1, 1], name="plot2", - **PLOT_STYLE + **PLOT_STYLE, ), ], {"x": ["2020-01-01", "2020-01-03"]}, @@ -156,7 +151,7 @@ def test_format_index_value(raw_value: str, expected_formatted_value: str): x_axis=[pd.Timestamp("2020-01-02")], y_axis=[1, 1, 1], name="plot2", - **PLOT_STYLE + **PLOT_STYLE, ), ], {"x": ["2020-01-01", "2020-01-03"], "x2": [4, 6]}, diff --git a/tests/data/snake_oil_data.py b/tests/data/snake_oil_data.py index c55cd4b0..fea1ba30 100644 --- a/tests/data/snake_oil_data.py +++ b/tests/data/snake_oil_data.py @@ -1,5 +1,5 @@ import io -import json + import pandas as pd diff --git a/tests/data/spe1_st/tests/conftest.py b/tests/data/spe1_st/tests/conftest.py index b9867978..7331df3f 100644 --- a/tests/data/spe1_st/tests/conftest.py +++ b/tests/data/spe1_st/tests/conftest.py @@ -4,9 +4,9 @@ @pytest.fixture(scope="session", autouse=True) def start_storage_server(): try: - from ert.services import StorageService as Storage + from ert.services import StorageService as Storage # noqa: PLC0415 except ImportError: - from ert.services import Storage + from ert.services import Storage # noqa: PLC0415 with Storage.start_server() as service: service.wait_until_ready(timeout=30) diff --git a/tests/data/spe1_st/tests/test_webviz_ert.py b/tests/data/spe1_st/tests/test_webviz_ert.py index 07a8cdd9..4c1e3219 100644 --- a/tests/data/spe1_st/tests/test_webviz_ert.py +++ b/tests/data/spe1_st/tests/test_webviz_ert.py @@ -1,18 +1,18 @@ import pytest -from webviz_ert.plugins import ( - ParameterComparison, - ResponseComparison, - ResponseCorrelation, - ObservationAnalyzer, -) from tests.conftest import ( - select_first, select_ensemble, + select_first, select_parameter, select_response, setup_plugin, verify_key_in_dropdown, ) +from webviz_ert.plugins import ( + ObservationAnalyzer, + ParameterComparison, + ResponseComparison, + ResponseCorrelation, +) parameter_keys = ["FIELD_PROPERTIES:POROSITY", "FIELD_PROPERTIES:X_MID_PERMEABILITY"] response_keys = ["WGPT:PROD", "WWPT:PROD", "WOPT:PROD", "WWIT:INJ"] @@ -39,7 +39,7 @@ def test_webviz_parameter_comparison(dash_duo): "default", ) - ensemble_name = select_first(dash_duo, "#" + plugin.uuid("ensemble-multi-selector")) + _ensemble_name = select_first(dash_duo, "#" + plugin.uuid("ensemble-multi-selector")) _verify_keys_in_menu( dash_duo, plugin, parameter_keys, "parameter-selector-multi-param" ) @@ -53,7 +53,6 @@ def test_webviz_response_correlation(dash_duo): ensemble = "default" response = "WOPT:PROD" parameter = "FIELD_PROPERTIES:POROSITY::0" - index = "2016-01-01" # Wait for the ensemble selector to be initialized dash_duo.wait_for_contains_text( @@ -96,7 +95,7 @@ def test_webviz_response_comparison(dash_duo): "default", ) - ensemble_name = select_first(dash_duo, "#" + plugin.uuid("ensemble-multi-selector")) + _ensemble_name = select_first(dash_duo, "#" + plugin.uuid("ensemble-multi-selector")) _verify_keys_in_menu( dash_duo, plugin, parameter_keys, "parameter-selector-multi-param" ) diff --git a/tests/models/test_ensemble_model.py b/tests/models/test_ensemble_model.py index 7ae9a637..241ec88e 100644 --- a/tests/models/test_ensemble_model.py +++ b/tests/models/test_ensemble_model.py @@ -1,8 +1,6 @@ -from webviz_ert.models import EnsembleModel import dash -from webviz_ert.plugins import ParameterComparison -from webviz_ert.plugins import ObservationAnalyzer -from webviz_ert.models import load_ensemble +from webviz_ert.models import EnsembleModel, load_ensemble +from webviz_ert.plugins import ObservationAnalyzer, ParameterComparison def test_ensemble_model(mock_data): @@ -16,7 +14,7 @@ def test_ensemble_model_labeled_parameters(mock_data): ens_model = EnsembleModel(ensemble_id=ens_id, project_id=None) assert ens_model.name == "nr_42" assert len(ens_model.parameters) == 5 - for param_name, parameter in ens_model.parameters.items(): + for param_name, _parameter in ens_model.parameters.items(): name, label = ( param_name.split("::", maxsplit=1) if "::" in param_name diff --git a/tests/plots/test_controller.py b/tests/plots/test_controller.py index 1d3e6a98..36b6b7c7 100644 --- a/tests/plots/test_controller.py +++ b/tests/plots/test_controller.py @@ -1,5 +1,6 @@ -import pandas as pd import numpy as np +import pandas as pd +from webviz_ert import assets from webviz_ert.controllers.multi_response_controller import ( _get_observation_plots, _get_realizations_plots, @@ -8,17 +9,14 @@ from webviz_ert.controllers.observation_response_controller import ( _get_univariate_misfits_boxplots, ) - -from webviz_ert.data_loader import get_ensembles -from webviz_ert.models import EnsembleModel, PriorModel from webviz_ert.models import ( + BarChartPlotModel, + BoxPlotModel, HistogramPlotModel, MultiHistogramPlotModel, - BoxPlotModel, ParallelCoordinatesPlotModel, - BarChartPlotModel, + PriorModel, ) -import webviz_ert.assets as assets def test_observation_plot_representation(): @@ -55,7 +53,8 @@ def test_observation_plot_representation(): def test_realizations_plot_representation(): - data = np.random.rand(200).reshape(-1, 20) + rng = np.random.default_rng() + data = rng.random(size=200).reshape(-1, 20) realization_df = pd.DataFrame(data=data, index=range(10), columns=range(20)) x_axis = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] plots = _get_realizations_plots( @@ -68,7 +67,8 @@ def test_realizations_plot_representation(): def test_realizations_statistics_plot_representation(): - data = np.random.rand(200).reshape(-1, 20) + rng = np.random.default_rng() + data = rng.random(size=200).reshape(-1, 20) realization_df = pd.DataFrame(data=data, index=range(10), columns=range(20)) x_axis = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] plots = _get_realizations_statistics_plots( @@ -86,7 +86,8 @@ def test_realizations_statistics_plot_representation(): def test_histogram_plot_representation(): - data = np.random.rand(20).reshape(-1, 20) + rng = np.random.default_rng() + data = rng.random(size=20).reshape(-1, 20) data_df = pd.DataFrame(data=data, index=range(1), columns=range(20)) data_df.index.name = "key_name" @@ -109,7 +110,8 @@ def test_multi_histogram_plot_representation(): zip(ensemble_names, colors[: len(ensemble_names)]) ): key = f"{ensemble_date}, {ensemble_name}" - data = np.random.rand(20).reshape(-1, 20) + rng = np.random.default_rng() + data = rng.random(size=20).reshape(-1, 20) data_df = pd.DataFrame(data=data, index=range(1), columns=range(20)) data_df.index.name = "KEY_NAME" data_dict[key] = data_df @@ -156,7 +158,8 @@ def test_parallel_coordinates_representation(): zip(ensemble_names, colors[: len(ensemble_names)]) ): key = f"{idx}, {ensemble_name}" - data = np.random.rand(50).reshape(-1, 5) + rng = np.random.default_rng() + data = rng.random(size=50).reshape(-1, 5) data_df = pd.DataFrame(data=data, columns=[f"PARAM_{i}" for i in range(5)]) data_df["ensemble_id"] = idx data_dict[key] = data_df @@ -175,7 +178,8 @@ def test_parallel_coordinates_representation(): def test_univariate_misfits_boxplot_representation(): - data = np.random.rand(200).reshape(-1, 20) + rng = np.random.default_rng() + data = rng.random(size=200).reshape(-1, 20) missfits_df = pd.DataFrame(data=data, index=range(10), columns=range(20)) ensemble_name = "test-ensemble" plots = _get_univariate_misfits_boxplots( @@ -194,7 +198,8 @@ def test_univariate_misfits_boxplot_representation(): def test_boxplot_representation(): - data = np.random.rand(10) + rng = np.random.default_rng() + data = rng.random(size=10) data_df = pd.DataFrame(data=data, index=range(10)) plot = BoxPlotModel( @@ -219,7 +224,8 @@ def test_barchart_representation(): zip(ensemble_names, colors[: len(ensemble_names)]) ): key = f"{idx}, {ensemble_name}" - data = np.random.rand(param_num) + rng = np.random.default_rng() + data = rng.random(size=param_num) data_df = pd.DataFrame( data=data, index=[f"PARAM_{i}" for i in range(param_num)] ) diff --git a/tests/test_data_loader.py b/tests/test_data_loader.py index 8180351e..bb97908b 100644 --- a/tests/test_data_loader.py +++ b/tests/test_data_loader.py @@ -1,4 +1,4 @@ -from webviz_ert.data_loader import get_ensembles, refresh_data, DataLoader +from webviz_ert.data_loader import get_ensembles, refresh_data def test_get_ensembles(mock_data): diff --git a/tests/views/test_ensemble_selector.py b/tests/views/test_ensemble_selector.py index 9786a8ff..d14fb09d 100644 --- a/tests/views/test_ensemble_selector.py +++ b/tests/views/test_ensemble_selector.py @@ -1,10 +1,8 @@ -import dash import pytest +from tests.conftest import get_options, select_ensemble, select_first, setup_plugin +from tests.data.snake_oil_data import all_ensemble_names from webviz_ert.assets import get_color from webviz_ert.plugins import ParameterComparison -from tests.conftest import select_first, get_options -from tests.data.snake_oil_data import all_ensemble_names -from tests.conftest import setup_plugin, select_ensemble @pytest.mark.browser_test diff --git a/tests/views/test_general_stuff.py b/tests/views/test_general_stuff.py index 69e0470a..2a84f812 100644 --- a/tests/views/test_general_stuff.py +++ b/tests/views/test_general_stuff.py @@ -1,11 +1,9 @@ import pytest -import dash -from tests.conftest import setup_plugin, select_ensemble - +from tests.conftest import select_ensemble, setup_plugin from webviz_ert.plugins import ( - ResponseComparison, ObservationAnalyzer, ParameterComparison, + ResponseComparison, ResponseCorrelation, ) diff --git a/tests/views/test_observation_view.py b/tests/views/test_observation_view.py index 5e8c7fd5..c5d3e86c 100644 --- a/tests/views/test_observation_view.py +++ b/tests/views/test_observation_view.py @@ -1,11 +1,10 @@ import pytest -from webviz_ert.plugins import ObservationAnalyzer from tests.conftest import ( - get_options, select_ensemble, - verify_key_in_dropdown, setup_plugin, + verify_key_in_dropdown, ) +from webviz_ert.plugins import ObservationAnalyzer @pytest.mark.browser_test diff --git a/tests/views/test_parameter_selector.py b/tests/views/test_parameter_selector.py index 749be3ce..8a3dd32f 100644 --- a/tests/views/test_parameter_selector.py +++ b/tests/views/test_parameter_selector.py @@ -1,8 +1,7 @@ import pytest - from selenium.webdriver.common.keys import Keys +from tests.conftest import select_by_name, select_ensemble, setup_plugin from webviz_ert.plugins import ParameterComparison -from tests.conftest import setup_plugin, select_ensemble, select_by_name @pytest.mark.browser_test @@ -78,7 +77,7 @@ def test_search_input_return_functionality( "#" + plugin.uuid("parameter-selector-multi-param"), "OP1_DIVERGENCE_SCALE", ) - first_elem, _ = parameter_selector_container.text.split("\n") + _first_elem, _ = parameter_selector_container.text.split("\n") param_selector_id = plugin.uuid("parameter-selector-multi-param") select_by_name(dash_duo, f"#{param_selector_id}", "BPR_138_PERSISTENCE") diff --git a/tests/views/test_plot_view.py b/tests/views/test_plot_view.py index 48123b82..3cb0c74c 100644 --- a/tests/views/test_plot_view.py +++ b/tests/views/test_plot_view.py @@ -1,12 +1,12 @@ import pytest -from webviz_ert.plugins._response_comparison import ResponseComparison from tests.conftest import ( - setup_plugin, select_ensemble, select_parameter, select_response, + setup_plugin, wait_a_bit, ) +from webviz_ert.plugins._response_comparison import ResponseComparison @pytest.mark.browser_test diff --git a/tests/views/test_response_correlation.py b/tests/views/test_response_correlation.py index a431ef53..01ee26ba 100644 --- a/tests/views/test_response_correlation.py +++ b/tests/views/test_response_correlation.py @@ -1,12 +1,12 @@ import pytest -from webviz_ert.plugins._response_correlation import ResponseCorrelation from tests.conftest import ( - setup_plugin, select_by_name, select_ensemble, - select_response, select_parameter, + select_response, + setup_plugin, ) +from webviz_ert.plugins._response_correlation import ResponseCorrelation @pytest.mark.browser_test diff --git a/tests/views/test_state_saving.py b/tests/views/test_state_saving.py index 27d21bf5..07886eca 100644 --- a/tests/views/test_state_saving.py +++ b/tests/views/test_state_saving.py @@ -1,15 +1,14 @@ -import pytest -from webviz_ert.plugins import ( - ResponseComparison, - WebvizErtPluginABC, -) import dash - +import pytest from tests.conftest import ( - setup_plugin, select_ensemble, select_parameter, select_response, + setup_plugin, +) +from webviz_ert.plugins import ( + ResponseComparison, + WebvizErtPluginABC, ) diff --git a/webviz_ert/__main__.py b/webviz_ert/__main__.py index 6aba9a0e..fb30f1b8 100644 --- a/webviz_ert/__main__.py +++ b/webviz_ert/__main__.py @@ -69,7 +69,7 @@ def handle_exit( logger.info("Session terminated by the user.\nThank you for using webviz-ert!") logger.info("=" * 32) sys.tracebacklimit = 0 - sys.stdout = open(os.devnull, "w") + sys.stdout = open(os.devnull, "w", encoding="utf-8") # noqa: SIM115 sys.exit() @@ -80,7 +80,7 @@ def create_config( temp_config: Any, experimental_mode: bool, ) -> None: - with open(config_file, "r") as f: + with open(config_file, "r", encoding="utf-8") as f: config_dict = yaml.safe_load(f) for page in config_dict["pages"]: for element in page["content"]: @@ -95,8 +95,7 @@ def create_config( def filter_experimental_pages( page: Dict[str, Any], experimental_mode: bool ) -> bool: - if "experimental" in page: - if page["experimental"]: + if "experimental" in page and page["experimental"]: return experimental_mode return True diff --git a/webviz_ert/assets/__init__.py b/webviz_ert/assets/__init__.py index 3122ecef..6018cac4 100644 --- a/webviz_ert/assets/__init__.py +++ b/webviz_ert/assets/__init__.py @@ -1,14 +1,14 @@ -import pkg_resources import json from pathlib import Path -from webviz_config.webviz_assets import WEBVIZ_ASSETS +import pkg_resources +from webviz_config.webviz_assets import WEBVIZ_ASSETS ASSETS_DIR = Path(pkg_resources.resource_filename("webviz_ert", "assets")) WEBVIZ_ASSETS.add(ASSETS_DIR / "bootstrap-grid.css") WEBVIZ_ASSETS.add(ASSETS_DIR / "bootstrap.min.css") WEBVIZ_ASSETS.add(ASSETS_DIR / "ert-style.css") -with open(ASSETS_DIR / "ert-style.json") as f: +with open(ASSETS_DIR / "ert-style.json", encoding="utf-8") as f: ERTSTYLE = json.load(f) COLOR_WHEEL = ERTSTYLE["ensemble-selector"]["color_wheel"] diff --git a/webviz_ert/controllers/__init__.py b/webviz_ert/controllers/__init__.py index 3697efd2..8b5db5dc 100644 --- a/webviz_ert/controllers/__init__.py +++ b/webviz_ert/controllers/__init__.py @@ -1,10 +1,27 @@ -from .ensemble_selector_controller import ensemble_list_selector_controller -from .multi_response_controller import multi_response_controller -from .observation_response_controller import observation_response_controller -from .multi_parameter_controller import multi_parameter_controller -from .controller_functions import response_options, parameter_options -from .plot_view_controller import plot_view_controller -from .parameter_comparison_controller import parameter_comparison_controller -from .parameter_selector_controller import parameter_selector_controller -from .response_correlation_controller import response_correlation_controller -from .element_dropdown_controller import element_dropdown_controller +from .controller_functions import parameter_options as parameter_options +from .controller_functions import response_options as response_options +from .element_dropdown_controller import ( + element_dropdown_controller as element_dropdown_controller, +) +from .ensemble_selector_controller import ( + ensemble_list_selector_controller as ensemble_list_selector_controller, +) +from .multi_parameter_controller import ( + multi_parameter_controller as multi_parameter_controller, +) +from .multi_response_controller import ( + multi_response_controller as multi_response_controller, +) +from .observation_response_controller import ( + observation_response_controller as observation_response_controller, +) +from .parameter_comparison_controller import ( + parameter_comparison_controller as parameter_comparison_controller, +) +from .parameter_selector_controller import ( + parameter_selector_controller as parameter_selector_controller, +) +from .plot_view_controller import plot_view_controller as plot_view_controller +from .response_correlation_controller import ( + response_correlation_controller as response_correlation_controller, +) diff --git a/webviz_ert/controllers/controller_functions.py b/webviz_ert/controllers/controller_functions.py index 0f5c397b..21bcf43d 100644 --- a/webviz_ert/controllers/controller_functions.py +++ b/webviz_ert/controllers/controller_functions.py @@ -1,10 +1,10 @@ from typing import List, Set -from webviz_ert.models import Response, EnsembleModel + +from webviz_ert.models import EnsembleModel, Response def _valid_response_option(response_filters: List[str], response: Response) -> bool: - if "historical" in response_filters: - if response.name.split(":")[0][-1] == "H": + if "historical" in response_filters and response.name.split(":")[0][-1] == "H": return False if "obs" in response_filters: @@ -32,7 +32,7 @@ def parameter_options(ensembles: List[EnsembleModel], union_keys: bool = True) - params_included: Set[str] = set() for ensemble in ensembles: if ensemble.parameters: - parameters = set([parameter for parameter in ensemble.parameters]) + parameters = set(ensemble.parameters) if not params_included: params_included = parameters elif union_keys: diff --git a/webviz_ert/controllers/element_dropdown_controller.py b/webviz_ert/controllers/element_dropdown_controller.py index abc07629..324a0d63 100644 --- a/webviz_ert/controllers/element_dropdown_controller.py +++ b/webviz_ert/controllers/element_dropdown_controller.py @@ -1,12 +1,11 @@ -import dash +from typing import Any, Dict, List, Optional, Tuple -from typing import List, Tuple, Dict, Optional, Any +import dash from dash.dependencies import Input, Output, State -from webviz_ert.models import DataType -from webviz_ert.plugins import WebvizErtPluginABC -from webviz_ert.models import load_ensemble from webviz_ert.controllers import parameter_options, response_options +from webviz_ert.models import DataType, load_ensemble +from webviz_ert.plugins import WebvizErtPluginABC def element_dropdown_controller( diff --git a/webviz_ert/controllers/ensemble_selector_controller.py b/webviz_ert/controllers/ensemble_selector_controller.py index 84fbcf5c..564187e3 100644 --- a/webviz_ert/controllers/ensemble_selector_controller.py +++ b/webviz_ert/controllers/ensemble_selector_controller.py @@ -1,9 +1,11 @@ -from typing import List, Dict, Any -from webviz_ert.plugins import WebvizErtPluginABC +from typing import Any, Dict, List + import dash from dash.dependencies import Input, Output, State + from webviz_ert.data_loader import get_ensembles, refresh_data from webviz_ert.models import load_ensemble +from webviz_ert.plugins import WebvizErtPluginABC def _get_non_selected_options(store: Dict[str, List]) -> List[Dict[str, str]]: @@ -24,7 +26,7 @@ def _setup_ensemble_selection_store(parent: WebvizErtPluginABC) -> Dict[str, Lis ensemble_id = ensemble_schema["id"] load_ensemble(parent, ensemble_id) - for ens_id, ensemble in parent.get_ensembles().items(): + for _ens_id, ensemble in parent.get_ensembles().items(): element = {"label": ensemble.name, "value": ensemble.id} ensemble_selection_store["options"].append(element) if ensemble.name in stored_selection: @@ -47,7 +49,7 @@ def ensemble_list_selector_controller( [ Input(parent.uuid("ensemble-multi-selector"), "value"), Input(parent.uuid("selected-ensemble-dropdown"), "value"), - Input(parent.uuid(f"ensemble-refresh-button"), "n_clicks"), + Input(parent.uuid("ensemble-refresh-button"), "n_clicks"), ], [ State(parent.uuid("selected-ensemble-dropdown"), "options"), @@ -93,7 +95,7 @@ def set_callback( [el["label"] for el in ensemble_selection_store["selected"]], ) - if triggered_id == parent.uuid(f"ensemble-refresh-button"): + if triggered_id == parent.uuid("ensemble-refresh-button"): parent.clear_ensembles() refresh_data(project_id=parent.project_identifier) parent.save_state("ensembles", []) @@ -114,7 +116,7 @@ def set_callback( container_ensemble_selector_multi_id = parent.uuid( "container-ensemble-selector-multi" ) - parameter_selector_button_id = parent.uuid(f"parameter-selector-button") + parameter_selector_button_id = parent.uuid("parameter-selector-button") @app.callback( [ diff --git a/webviz_ert/controllers/multi_parameter_controller.py b/webviz_ert/controllers/multi_parameter_controller.py index 6d3b59ec..f218c9d4 100644 --- a/webviz_ert/controllers/multi_parameter_controller.py +++ b/webviz_ert/controllers/multi_parameter_controller.py @@ -1,12 +1,13 @@ +from typing import Any, List, Mapping, Tuple + import dash import plotly.graph_objects as go - -from typing import List, Tuple, Any, Optional, Mapping, Dict +from dash.dependencies import MATCH, Input, Output, State from dash.exceptions import PreventUpdate -from dash.dependencies import Input, Output, State, MATCH + +from webviz_ert import assets from webviz_ert.models import MultiHistogramPlotModel, load_ensemble from webviz_ert.plugins import WebvizErtPluginABC -from webviz_ert import assets def multi_parameter_controller(parent: WebvizErtPluginABC, app: dash.Dash) -> None: diff --git a/webviz_ert/controllers/multi_response_controller.py b/webviz_ert/controllers/multi_response_controller.py index 3342f7dd..76cb5a40 100644 --- a/webviz_ert/controllers/multi_response_controller.py +++ b/webviz_ert/controllers/multi_response_controller.py @@ -1,22 +1,23 @@ +import datetime import logging +from copy import deepcopy +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union + import dash import pandas as pd -import datetime import plotly.graph_objects as go -import webviz_ert.assets as assets - -from copy import deepcopy -from typing import List, Dict, Union, Any, Optional, Type, Tuple, TYPE_CHECKING -from dash.dependencies import Input, Output, State, ALL, MATCH +from dash.dependencies import MATCH, Input, Output, State from dash.exceptions import PreventUpdate -from webviz_ert.plugins import WebvizErtPluginABC + +from webviz_ert import assets from webviz_ert.models import ( - ResponsePlotModel, - Response, + AxisType, PlotModel, + Response, + ResponsePlotModel, load_ensemble, - AxisType, ) +from webviz_ert.plugins import WebvizErtPluginABC if TYPE_CHECKING: from .ensemble_model import EnsembleModel @@ -31,13 +32,10 @@ def _get_realizations_plots( style: Optional[Dict] = None, ensemble_name: str = "", ) -> List[PlotModel]: - if style: - _style = style - else: - _style = assets.ERTSTYLE["response-plot"]["response"].copy() + _style = style if style else assets.ERTSTYLE["response-plot"]["response"].copy() _style.update({"line": {"color": color}}) _style.update({"marker": {"color": color}}) - realizations_data = list() + realizations_data = [] for idx, realization in enumerate(realizations_df): plot = PlotModel( x_axis=x_axis, @@ -45,7 +43,7 @@ def _get_realizations_plots( text=f"Realization: {realization} Ensemble: {ensemble_name}", name=ensemble_name, legendgroup=ensemble_name, - showlegend=False if idx > 0 else True, + showlegend=not idx > 0, **_style, ) realizations_data.append(plot) @@ -69,7 +67,7 @@ def _get_realizations_statistics_plots( mean_data = PlotModel( x_axis=x_axis, y_axis=_mean, - text=f"Mean", + text="Mean", name=f"Mean {ensemble_name}", **style_mean, ) @@ -102,11 +100,11 @@ def _get_observation_plots( y_axis=data, text=attributes, name=f"Observation_{ensemble}", - error_y=dict( - type="data", # value of error bar given in data coordinates - array=stds.values, - visible=True, - ), + error_y={ + "type": "data", # value of error bar given in data coordinates + "array": stds.values, + "visible": True, + }, meta=metadata, **style, ) @@ -145,7 +143,7 @@ def _create_response_plot( else: observations = [] - ensemble_plot = ResponsePlotModel(realizations, observations, dict()) + ensemble_plot = ResponsePlotModel(realizations, observations, {}) return ensemble_plot diff --git a/webviz_ert/controllers/observation_response_controller.py b/webviz_ert/controllers/observation_response_controller.py index 90080642..43e69a6f 100644 --- a/webviz_ert/controllers/observation_response_controller.py +++ b/webviz_ert/controllers/observation_response_controller.py @@ -1,21 +1,21 @@ +from typing import Any, List, Optional + import dash import pandas as pd import plotly.graph_objects as go - -from copy import deepcopy -from typing import List, Dict, Union, Optional, Mapping, Any from dash.dependencies import Input, Output, State from dash.exceptions import PreventUpdate + +from webviz_ert import assets from webviz_ert.controllers.controller_functions import response_options -from webviz_ert.plugins import WebvizErtPluginABC from webviz_ert.models import ( - ResponsePlotModel, BoxPlotModel, - Response, MultiHistogramPlotModel, + Response, + ResponsePlotModel, load_ensemble, ) -from webviz_ert import assets +from webviz_ert.plugins import WebvizErtPluginABC def _get_univariate_misfits_boxplots( @@ -23,9 +23,8 @@ def _get_univariate_misfits_boxplots( ) -> List[BoxPlotModel]: if misfits_df is None: return [] - x_axis = misfits_df.columns realization_names = [f"Realization {name}" for name in misfits_df.index.values] - misfit_plots = list() + misfit_plots = [] for misfits in misfits_df: plot = BoxPlotModel( y_axis=misfits_df[misfits].abs().values, @@ -50,10 +49,10 @@ def _create_misfits_plot( ensemble_plot = ResponsePlotModel( realizations, [], - dict( - hovermode="closest", - uirevision=True, - ), + { + "hovermode":"closest", + "uirevision":True, + }, ) return ensemble_plot @@ -120,7 +119,7 @@ def update_graph( misfits_type: str, selected_ensembles: List[str], ) -> go.Figure: - if not response or response == "" or not selected_ensembles: + if not response or not selected_ensembles: return go.Figure() if misfits_type == "Summary": diff --git a/webviz_ert/controllers/parameter_comparison_controller.py b/webviz_ert/controllers/parameter_comparison_controller.py index fce9c4aa..55abddab 100644 --- a/webviz_ert/controllers/parameter_comparison_controller.py +++ b/webviz_ert/controllers/parameter_comparison_controller.py @@ -1,14 +1,15 @@ +from typing import Any, Dict, List, Optional, Tuple + import dash import plotly.graph_objects as go -from typing import Any, List, Optional, Dict, Tuple - from dash.dependencies import Input, Output, State + +from webviz_ert import assets from webviz_ert.models import ( - load_ensemble, ParallelCoordinatesPlotModel, + load_ensemble, ) from webviz_ert.plugins import WebvizErtPluginABC -from webviz_ert import assets def parameter_comparison_controller(parent: WebvizErtPluginABC, app: dash.Dash) -> None: diff --git a/webviz_ert/controllers/parameter_selector_controller.py b/webviz_ert/controllers/parameter_selector_controller.py index e0ab710c..5f09dda9 100644 --- a/webviz_ert/controllers/parameter_selector_controller.py +++ b/webviz_ert/controllers/parameter_selector_controller.py @@ -1,15 +1,15 @@ -import dash +from typing import Any, Dict, List, Optional, Tuple -from typing import List, Any, Tuple, Dict, Optional -from dash.exceptions import PreventUpdate +import dash from dash.dependencies import Input, Output, State +from dash.exceptions import PreventUpdate -from webviz_ert.plugins import WebvizErtPluginABC +from webviz_ert.controllers import parameter_options, response_options from webviz_ert.models import ( load_ensemble, ) -from webviz_ert.controllers import parameter_options, response_options from webviz_ert.models.data_model import DataType +from webviz_ert.plugins import WebvizErtPluginABC def _filter_match(_filter: str, key: str) -> bool: @@ -101,7 +101,7 @@ def update_parameter_selection( else: raise PreventUpdate elif triggered_id == parameter_selector_multi_id: - selected_params = [] if not selected_params else selected_params + selected_params = selected_params if selected_params else [] parameters = ( [] if not parameters @@ -132,14 +132,14 @@ def update_parameter_selection( def update_parameter_options( _: Any, shown_parameters: Optional[List[str]] ) -> Tuple[List[Dict], List[str]]: - shown_parameters = [] if not shown_parameters else shown_parameters + shown_parameters = shown_parameters if shown_parameters else [] selected_opts = [{"label": param, "value": param} for param in shown_parameters] return selected_opts, shown_parameters container_parameter_selector_multi_id = parent.uuid( f"container-parameter-selector-multi-{data_type}" ) - parameter_selector_button_id = parent.uuid(f"parameter-selector-button") + parameter_selector_button_id = parent.uuid("parameter-selector-button") @app.callback( Output(container_parameter_selector_multi_id, "className"), diff --git a/webviz_ert/controllers/plot_view_controller.py b/webviz_ert/controllers/plot_view_controller.py index b8cbc362..606f2478 100644 --- a/webviz_ert/controllers/plot_view_controller.py +++ b/webviz_ert/controllers/plot_view_controller.py @@ -1,17 +1,16 @@ +from typing import Any, List, Optional, Union + import dash import dash_bootstrap_components as dbc - from dash import html -from typing import List, Union, Any, Dict, Tuple, Optional, Mapping -from dash.development.base_component import Component from dash.dependencies import Input, Output, State +from dash.development.base_component import Component import webviz_ert.controllers -import webviz_ert.assets as assets - -from webviz_ert.views import response_view, parameter_view -from webviz_ert.plugins import WebvizErtPluginABC +from webviz_ert import assets from webviz_ert.models import DataType +from webviz_ert.plugins import WebvizErtPluginABC +from webviz_ert.views import parameter_view, response_view def _new_child(parent: WebvizErtPluginABC, plot: str, data_type: DataType) -> Component: @@ -57,8 +56,8 @@ def update_plot_selection( selection: Optional[List[str]], current_plots: Optional[List[str]], ) -> List[str]: - selection = [] if not selection else selection - current_plots = [] if not current_plots else current_plots + selection = selection if selection else [] + current_plots = current_plots if current_plots else [] for plot in current_plots.copy(): if plot not in selection: current_plots.remove(plot) diff --git a/webviz_ert/controllers/response_correlation_controller.py b/webviz_ert/controllers/response_correlation_controller.py index 4b3f85c9..889ff192 100644 --- a/webviz_ert/controllers/response_correlation_controller.py +++ b/webviz_ert/controllers/response_correlation_controller.py @@ -1,25 +1,25 @@ -import pandas as pd -import plotly.graph_objects as go +from copy import deepcopy +from typing import Any, Dict, List, Optional, Tuple, Union + import dash -import numpy as np import dash_bootstrap_components as dbc - -from typing import List, Optional, Dict, Tuple, Any, Union -from copy import deepcopy +import numpy as np +import pandas as pd +import plotly.graph_objects as go from dash import html +from dash.dependencies import Input, Output, State from dash.development.base_component import Component from dash.exceptions import PreventUpdate -from dash.dependencies import Input, Output, State -from plotly.subplots import make_subplots from plotly.graph_objs.layout import XAxis, YAxis +from plotly.subplots import make_subplots -from webviz_ert.plugins import WebvizErtPluginABC -from webviz_ert.models import load_ensemble, BarChartPlotModel, PlotModel, AxisType +from webviz_ert import assets from webviz_ert.controllers.multi_response_controller import ( _get_observation_plots, axis_label_for_ensemble_response, ) -from webviz_ert import assets +from webviz_ert.models import AxisType, BarChartPlotModel, PlotModel, load_ensemble +from webviz_ert.plugins import WebvizErtPluginABC def response_correlation_controller(parent: WebvizErtPluginABC, app: dash.Dash) -> None: @@ -233,20 +233,20 @@ def disable_figure() -> Tuple[Dict, go.Figure, Dict, Dict]: fig = go.Figure(layout_yaxis_range=[-1, len(obs_plots)]) layout = assets.ERTSTYLE["figure"]["layout"].copy() layout.update( - dict( - xaxis=XAxis(title="Date", showgrid=False, fixedrange=True), - xaxis2=XAxis( + { + "xaxis": XAxis(title="Date", showgrid=False, fixedrange=True), + "xaxis2": XAxis( overlaying="x", title="Index", side="top", showgrid=False, fixedrange=True, ), - yaxis=YAxis(fixedrange=True), - dragmode="select", - template="plotly_white", - height=300, - ) + "yaxis": YAxis(fixedrange=True), + "dragmode": "select", + "template": "plotly_white", + "height": 300, + } ) fig.update_layout(layout) @@ -366,7 +366,7 @@ def update_response_overview_plot( if selected_obs_idx is not None: fig.add_vline( x=selected_obs_idx, - line=dict(color="red", dash="dash", width=4), + line={"color": "red", "dash": "dash", "width": 4}, ) for plot in obs_plots: @@ -611,7 +611,7 @@ def update_active_resp_index_and_param( def _get_selected_ensembles_from_store( - ensemble_selection_store: Dict[str, List] + ensemble_selection_store: Dict[str, List], ) -> Optional[List[str]]: if ensemble_selection_store: return [ @@ -645,7 +645,7 @@ def _define_style_ensemble(index: int, x_axis: pd.Index) -> Dict: def _layout_figure(x_axis_label: str) -> dict: layout = assets.ERTSTYLE["figure"]["layout"].copy() - layout.update(dict(showlegend=False)) + layout.update({"showlegend": False}) layout.update(clickmode="event+select") layout.update({"xaxis": {"title": {"text": x_axis_label}}}) layout.update(assets.ERTSTYLE["figure"]["layout-value-y-axis-label"]) @@ -725,7 +725,7 @@ def _add_plots_to_multiplot( for plot in _plots: fig.add_trace(plot.repr, 1, 1) - for ensemble_name in _param_plots: + for ensemble_name, val in _param_plots.items(): fig.add_trace( { "type": "histogram", @@ -733,14 +733,14 @@ def _add_plots_to_multiplot( "hoverlabel": { "namelength": -1, }, - "x": _param_plots[ensemble_name], + "x": val, "showlegend": False, "marker_color": _colors[ensemble_name], }, row_histograms, 1, ) - for ensemble_name in _resp_plots: + for ensemble_name, val in _resp_plots.items(): fig.add_trace( { "type": "histogram", @@ -748,7 +748,7 @@ def _add_plots_to_multiplot( "hoverlabel": { "namelength": -1, }, - "x": _resp_plots[ensemble_name], + "x": val, "showlegend": False, "marker_color": _colors[ensemble_name], }, @@ -791,10 +791,10 @@ def _observation_index_plot(obs: Any, name: str, plot_idx: int) -> PlotModel: style = deepcopy(assets.ERTSTYLE["observation-selection-plot"]) marker_color = assets.get_color(plot_idx) style.update( - dict( - marker={"color": marker_color, "size": 9}, - xaxis="x2" if obs.axis_type == AxisType.INDEX else "x", - ) + { + "marker": {"color": marker_color, "size": 9}, + "xaxis": "x2" if obs.axis_type == AxisType.INDEX else "x", + } ) return PlotModel( x_axis=obs.axis, diff --git a/webviz_ert/data_loader/__init__.py b/webviz_ert/data_loader/__init__.py index 2c5d14ab..e30e8e4f 100644 --- a/webviz_ert/data_loader/__init__.py +++ b/webviz_ert/data_loader/__init__.py @@ -1,7 +1,8 @@ +import contextlib import io import logging from collections import defaultdict -from typing import Any, Dict, List, Mapping, MutableMapping, Optional, Tuple +from typing import Any, List, Mapping, MutableMapping, Optional, Tuple import pandas as pd import requests @@ -12,7 +13,7 @@ def get_connection_info(project_id: Optional[str] = None) -> Mapping[str, str]: - from ert.shared.storage.connection import get_info + from ert.shared.storage.connection import get_info # noqa: PLC0415 if project_id not in connection_info_map: info = get_info(project_id) @@ -99,7 +100,7 @@ def _post( def get_all_ensembles(self) -> list: try: - experiments = self._get(url=f"experiments").json() + experiments = self._get(url="experiments").json() return [ self.get_ensemble(ensemble_id) for experiment in experiments @@ -107,35 +108,35 @@ def get_all_ensembles(self) -> list: ] except DataLoaderException as e: logger.error(e) - return list() + return [] def get_ensemble(self, ensemble_id: str) -> dict: try: return self._get(url=f"ensembles/{ensemble_id}").json() except DataLoaderException as e: logger.error(e) - return dict() + return {} def get_ensemble_responses(self, ensemble_id: str) -> dict: try: return self._get(url=f"ensembles/{ensemble_id}/responses").json() except DataLoaderException as e: logger.error(e) - return dict() + return {} def get_ensemble_userdata(self, ensemble_id: str) -> dict: try: return self._get(url=f"ensembles/{ensemble_id}/userdata").json() except DataLoaderException as e: logger.error(e) - return dict() + return {} def get_ensemble_parameters(self, ensemble_id: str) -> list: try: return self._get(url=f"ensembles/{ensemble_id}/parameters").json() except DataLoaderException as e: logger.error(e) - return list() + return [] def get_record_labels(self, ensemble_id: str, name: str) -> list: try: @@ -144,7 +145,7 @@ def get_record_labels(self, ensemble_id: str, name: str) -> list: ).json() except DataLoaderException as e: logger.error(e) - return list() + return [] def get_experiment_priors(self, experiment_id: str) -> dict: try: @@ -152,7 +153,7 @@ def get_experiment_priors(self, experiment_id: str) -> dict: return experiment["priors"] except RuntimeError as e: logger.error(e) - return dict() + return {} def get_ensemble_parameter_data( self, @@ -198,10 +199,8 @@ def get_ensemble_record_data( try: df.index = df.index.astype(int) except (TypeError, ValueError): - try: + with contextlib.suppress((TypeError, ValueError)): df.index = df.index.map(pd.Timestamp) - except ValueError: - pass df = df.sort_index() return df @@ -216,7 +215,7 @@ def get_ensemble_record_observations( ).json() except DataLoaderException as e: logger.error(e) - return list() + return [] def compute_misfit( self, ensemble_id: str, response_name: str, summary: bool diff --git a/webviz_ert/models/__init__.py b/webviz_ert/models/__init__.py index e51a898f..3fb7b089 100644 --- a/webviz_ert/models/__init__.py +++ b/webviz_ert/models/__init__.py @@ -1,19 +1,20 @@ -from typing import List, Union, Optional, TYPE_CHECKING import datetime +from typing import TYPE_CHECKING, List, Optional, Union + import pandas as pd def indexes_to_axis( - indexes: Optional[List[Union[int, str, datetime.datetime]]] + indexes: Optional[List[Union[int, str, datetime.datetime]]], ) -> Optional[List[Union[int, str, datetime.datetime]]]: try: if indexes and type(indexes[0]) is str and not str(indexes[0]).isnumeric(): - return list(map(lambda dt: pd.Timestamp(dt), indexes)) + return [pd.Timestamp(dt) for dt in indexes] if indexes and type(indexes[0]) is str and str(indexes[0]).isnumeric(): - return list(map(lambda idx: int(str(idx)), indexes)) + return [int(str(idx)) for idx in indexes] return indexes except ValueError as e: - raise ValueError("Could not parse indexes as either int or dates", e) + raise ValueError("Could not parse indexes as either int or dates", e) from e if TYPE_CHECKING: @@ -33,18 +34,34 @@ def load_ensemble( return ensemble -from .data_model import DataType, AxisType -from .observation import Observation -from .realization import Realization -from .response import Response +from .data_model import AxisType as AxisType +from .data_model import DataType as DataType +from .observation import Observation as Observation +from .realization import Realization as Realization +from .response import Response as Response + +from .plot_model import ( + BarChartPlotModel as BarChartPlotModel, +) +from .plot_model import ( + BoxPlotModel as BoxPlotModel, +) +from .plot_model import ( + HistogramPlotModel as HistogramPlotModel, +) from .plot_model import ( - PlotModel, - ResponsePlotModel, - HistogramPlotModel, - MultiHistogramPlotModel, - BoxPlotModel, - ParallelCoordinatesPlotModel, - BarChartPlotModel, + MultiHistogramPlotModel as MultiHistogramPlotModel, ) -from .parameter_model import PriorModel, ParametersModel +from .plot_model import ( + ParallelCoordinatesPlotModel as ParallelCoordinatesPlotModel, +) +from .plot_model import ( + PlotModel as PlotModel, +) +from .plot_model import ( + ResponsePlotModel as ResponsePlotModel, +) + +from .parameter_model import ParametersModel as ParametersModel +from .parameter_model import PriorModel as PriorModel from .ensemble_model import EnsembleModel diff --git a/webviz_ert/models/ensemble_model.py b/webviz_ert/models/ensemble_model.py index 77b23796..902495e1 100644 --- a/webviz_ert/models/ensemble_model.py +++ b/webviz_ert/models/ensemble_model.py @@ -1,8 +1,9 @@ -import json +from typing import Dict, List, Mapping, Optional + import pandas as pd -from typing import Mapping, List, Dict, Union, Any, Optional -from webviz_ert.data_loader import get_data_loader, DataLoaderException -from webviz_ert.models import Response, PriorModel, ParametersModel + +from webviz_ert.data_loader import get_data_loader +from webviz_ert.models import ParametersModel, PriorModel, Response def _create_parameter_models( @@ -14,7 +15,7 @@ def _create_parameter_models( parameters = {} for param in parameters_names: key = param - prior_schema = priors.get(key, None) + prior_schema = priors.get(key) prior = None if prior_schema: prior = PriorModel( diff --git a/webviz_ert/models/observation.py b/webviz_ert/models/observation.py index 8179a750..7b65fb6d 100644 --- a/webviz_ert/models/observation.py +++ b/webviz_ert/models/observation.py @@ -1,8 +1,9 @@ -from typing import Dict, Optional, List, Union -import pandas as pd import datetime +from typing import Dict, List, Optional, Union + +import pandas as pd -from webviz_ert.models import indexes_to_axis, AxisType +from webviz_ert.models import AxisType, indexes_to_axis class Observation: diff --git a/webviz_ert/models/parameter_model.py b/webviz_ert/models/parameter_model.py index 24545410..ddc55e83 100644 --- a/webviz_ert/models/parameter_model.py +++ b/webviz_ert/models/parameter_model.py @@ -1,5 +1,7 @@ +from typing import Any, List, Union + import pandas as pd -from typing import List, Any, Optional, Union + from webviz_ert.data_loader import get_data_loader diff --git a/webviz_ert/models/plot_model.py b/webviz_ert/models/plot_model.py index 277b99b1..ec799214 100644 --- a/webviz_ert/models/plot_model.py +++ b/webviz_ert/models/plot_model.py @@ -1,13 +1,14 @@ -from typing import List, Any, Dict, Mapping, Optional, TYPE_CHECKING, Union -import numpy as np +import logging import math +from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Union + +import numpy as np import pandas as pd -import logging -import plotly.graph_objects as go import plotly.figure_factory as ff -from dateutil.parser import isoparse -from scipy.stats import norm, lognorm, truncnorm, uniform, loguniform, triang -import webviz_ert.assets as assets +import plotly.graph_objects as go +from scipy.stats import lognorm, loguniform, norm, triang, truncnorm, uniform + +from webviz_ert import assets from webviz_ert.models.data_model import AxisType if TYPE_CHECKING: @@ -110,28 +111,24 @@ def __init__(self, **kwargs: Any): self._y_axis = kwargs["y_axis"] self._name = kwargs["name"] self._color = kwargs["color"] - self._customdata = kwargs["customdata"] if "customdata" in kwargs else None - self._hovertemplate = ( - kwargs["hovertemplate"] if "hovertemplate" in kwargs else None - ) - self._ensemble_name = ( - kwargs["ensemble_name"] if "ensemble_name" in kwargs else None - ) + self._customdata = kwargs.get("customdata", None) + self._hovertemplate = kwargs.get("hovertemplate", None) + self._ensemble_name = kwargs.get("ensemble_name", None) @property def repr(self) -> go.Box: - repr_dict = dict( - y=self._y_axis, - x0=f"{self._name}", - legendgroup=self.name, - name=self.display_name, - boxpoints="all", - jitter=0.3, - pointpos=-1.8, - marker_color=self._color, - customdata=self._customdata, - hovertemplate=self._hovertemplate, - ) + repr_dict = { + "y": self._y_axis, + "x0": f"{self._name}", + "legendgroup": self.name, + "name": self.display_name, + "boxpoints": "all", + "jitter": 0.3, + "pointpos": -1.8, + "marker_color": self._color, + "customdata": self._customdata, + "hovertemplate": self._hovertemplate, + } return go.Box(repr_dict) @@ -161,7 +158,7 @@ def __init__( @property def plot_ids(self) -> Mapping[int, str]: - return {plot_idx: ens_name for plot_idx, ens_name in enumerate(self.data)} + return dict(enumerate(self.data)) @property def data(self) -> Mapping[str, pd.DataFrame]: @@ -177,9 +174,9 @@ def repr(self) -> go.Figure: y=self.data[ens_name].index, orientation="h", name=ens_name, - marker=dict( - color=self._colors[ens_name], - ), + marker={ + "color": self._colors[ens_name], + }, ), ) _layout = assets.ERTSTYLE["figure"]["layout"].copy() @@ -215,19 +212,19 @@ def __init__(self, **kwargs: Any): @property def repr(self) -> Union[go.Scattergl, go.Scatter]: - repr_dict = dict( - x=self._x_axis, - y=self._y_axis, - text=self._text, - name=self.display_name, - mode=self._mode, - error_y=self._error_y, - xaxis=self._xaxis, - connectgaps=True, - hoverlabel=self._hoverlabel, - meta=self._meta, - showlegend=self.showlegend, - ) + repr_dict = { + "x": self._x_axis, + "y": self._y_axis, + "text": self._text, + "name": self.display_name, + "mode": self._mode, + "error_y": self._error_y, + "xaxis": self._xaxis, + "connectgaps": True, + "hoverlabel": self._hoverlabel, + "meta": self._meta, + "showlegend": self.showlegend, + } if self.legendgroup: repr_dict["legendgroup"] = self.legendgroup if self._line: @@ -316,7 +313,7 @@ def __init__( colors: Mapping[str, str], hist: bool = True, kde: bool = True, - priors: Dict = {}, + priors: Dict = {}, # noqa: B006 bin_count: Optional[int] = None, ): self._hist_enabled = hist @@ -403,7 +400,7 @@ def __init__( @property def plot_ids(self) -> Mapping[int, str]: - return {plot_idx: parameter for plot_idx, parameter in enumerate(self.data)} + return dict(enumerate(self.data)) @property def data(self) -> Mapping[str, pd.DataFrame]: @@ -425,20 +422,20 @@ def repr(self) -> go.Figure: # create parallel coordinates dimension list dimensions = [] for parameter in data_df: - dimensions.append(dict(label=parameter, values=data_df[parameter])) + dimensions.append({"label": parameter, "values": data_df[parameter]}) fig.add_trace( go.Parcoords( - line=dict( - color=ensemble_ids, - colorscale=colors, - showscale=True, - colorbar=dict( - tickvals=list(range(0, len(self.data))), - ticktext=list(self.data.keys()), - len=0.2 * len(self.data), - title="Ensemble", - ), - ), + line={ + "color": ensemble_ids, + "colorscale": colors, + "showscale": True, + "colorbar": { + "tickvals": list(range(0, len(self.data))), + "ticktext": list(self.data.keys()), + "len": 0.2 * len(self.data), + "title": "Ensemble", + }, + }, dimensions=dimensions, labelangle=45, labelside="bottom", diff --git a/webviz_ert/models/realization.py b/webviz_ert/models/realization.py index 07c8adf4..5c5626b2 100644 --- a/webviz_ert/models/realization.py +++ b/webviz_ert/models/realization.py @@ -1,6 +1,7 @@ +import math from typing import List, Optional + import pandas as pd -import math class Realization: diff --git a/webviz_ert/models/response.py b/webviz_ert/models/response.py index 114974bd..60773f0c 100644 --- a/webviz_ert/models/response.py +++ b/webviz_ert/models/response.py @@ -1,8 +1,9 @@ -from typing import List, Mapping, Optional, Any +from typing import Any, List, Mapping, Optional + import pandas as pd -from webviz_ert.data_loader import get_data_loader, DataLoader -from webviz_ert.models import Observation, AxisType +from webviz_ert.data_loader import DataLoader, get_data_loader +from webviz_ert.models import AxisType, Observation class Response: diff --git a/webviz_ert/plugins/__init__.py b/webviz_ert/plugins/__init__.py index c162ccf6..85b33310 100644 --- a/webviz_ert/plugins/__init__.py +++ b/webviz_ert/plugins/__init__.py @@ -1,5 +1,5 @@ -from ._webviz_ert import WebvizErtPluginABC -from ._response_comparison import ResponseComparison -from ._observation_analyzer import ObservationAnalyzer -from ._parameter_comparison import ParameterComparison -from ._response_correlation import ResponseCorrelation +from ._webviz_ert import WebvizErtPluginABC as WebvizErtPluginABC +from ._response_comparison import ResponseComparison as ResponseComparison +from ._observation_analyzer import ObservationAnalyzer as ObservationAnalyzer +from ._parameter_comparison import ParameterComparison as ParameterComparison +from ._response_correlation import ResponseCorrelation as ResponseCorrelation diff --git a/webviz_ert/plugins/_observation_analyzer.py b/webviz_ert/plugins/_observation_analyzer.py index 22ad3c4c..036770c3 100644 --- a/webviz_ert/plugins/_observation_analyzer.py +++ b/webviz_ert/plugins/_observation_analyzer.py @@ -1,10 +1,12 @@ +from typing import Dict, List + import dash -import webviz_ert.models -import webviz_ert.controllers from dash.development.base_component import Component -from typing import List, Dict -from webviz_ert.views import ensemble_selector_list, response_obs_view + +import webviz_ert.controllers +import webviz_ert.models from webviz_ert.plugins import WebvizErtPluginABC +from webviz_ert.views import ensemble_selector_list, response_obs_view class ObservationAnalyzer(WebvizErtPluginABC): @@ -54,7 +56,7 @@ def tour_steps(self) -> List[Dict[str, str]]: "content": "List of currently selected ensembles.", }, { - "id": self.uuid(f"ensemble-refresh-button"), + "id": self.uuid("ensemble-refresh-button"), "content": ( "Forces a refresh of all ensemble data including parameter and response data." ), diff --git a/webviz_ert/plugins/_parameter_comparison.py b/webviz_ert/plugins/_parameter_comparison.py index 4f99229e..dafece6a 100644 --- a/webviz_ert/plugins/_parameter_comparison.py +++ b/webviz_ert/plugins/_parameter_comparison.py @@ -1,17 +1,18 @@ +from typing import Dict, List + import dash import dash_bootstrap_components as dbc -import webviz_ert.controllers -import webviz_ert.models from dash.development.base_component import Component -from typing import List, Dict +import webviz_ert.controllers +import webviz_ert.models +from webviz_ert.models.data_model import DataType +from webviz_ert.plugins import WebvizErtPluginABC from webviz_ert.views import ( ensemble_selector_list, parallel_coordinates_view, parameter_selector_view, ) -from webviz_ert.plugins import WebvizErtPluginABC -from webviz_ert.models.data_model import DataType class ParameterComparison(WebvizErtPluginABC): @@ -80,13 +81,13 @@ def tour_steps(self) -> List[Dict[str, str]]: "content": "List of currently selected ensembles.", }, { - "id": self.uuid(f"ensemble-refresh-button"), + "id": self.uuid("ensemble-refresh-button"), "content": ( "Forces a refresh of all ensemble data including parameter and response data." ), }, { - "id": self.uuid(f"parameter-selector-multi-param"), + "id": self.uuid("parameter-selector-multi-param"), "content": ( "List of parameters. This list is populated only" " if at least one ensemble is selected." @@ -95,7 +96,7 @@ def tour_steps(self) -> List[Dict[str, str]]: ), }, { - "id": self.uuid(f"parameter-deactivator-param"), + "id": self.uuid("parameter-deactivator-param"), "content": ( "List of currently selected parameters." "Every selected parameter is visualized in the parallel coordinates plot," @@ -104,7 +105,7 @@ def tour_steps(self) -> List[Dict[str, str]]: ), }, { - "id": self.uuid(f"parameter-selector-filter-param"), + "id": self.uuid("parameter-selector-filter-param"), "content": ( "Search field. The parameter list will show only" " elements that contain the search characters" diff --git a/webviz_ert/plugins/_response_comparison.py b/webviz_ert/plugins/_response_comparison.py index 9e7bec4b..38f65f96 100644 --- a/webviz_ert/plugins/_response_comparison.py +++ b/webviz_ert/plugins/_response_comparison.py @@ -1,16 +1,17 @@ +from typing import Dict, List + import dash +from dash.development.base_component import Component + import webviz_ert.controllers import webviz_ert.models -from dash.development.base_component import Component -from typing import List, Dict +from webviz_ert.models.data_model import DataType +from webviz_ert.plugins import WebvizErtPluginABC from webviz_ert.views import ( - ensemble_selector_list, plot_view_body, plot_view_header, plot_view_menu, ) -from webviz_ert.models.data_model import DataType -from webviz_ert.plugins import WebvizErtPluginABC class ResponseComparison(WebvizErtPluginABC): @@ -61,7 +62,7 @@ def tour_steps(self) -> List[Dict[str, str]]: "content": "List of currently selected ensembles.", }, { - "id": self.uuid(f"ensemble-refresh-button"), + "id": self.uuid("ensemble-refresh-button"), "content": ( "Forces a refresh of all ensemble data including parameter and response data." ), @@ -71,7 +72,7 @@ def tour_steps(self) -> List[Dict[str, str]]: "content": "Response section.", }, { - "id": self.uuid(f"parameter-selector-multi-resp"), + "id": self.uuid("parameter-selector-multi-resp"), "content": ( "List of responses. This list is populated only" " if at least one ensemble is selected." @@ -80,11 +81,11 @@ def tour_steps(self) -> List[Dict[str, str]]: ), }, { - "id": self.uuid(f"parameter-deactivator-resp"), + "id": self.uuid("parameter-deactivator-resp"), "content": "List of currently selected responses.", }, { - "id": self.uuid(f"parameter-selector-filter-resp"), + "id": self.uuid("parameter-selector-filter-resp"), "content": ( "Response search field. The response list will show only" " elements that contain the search characters" @@ -95,7 +96,7 @@ def tour_steps(self) -> List[Dict[str, str]]: "content": "Parameter section", }, { - "id": self.uuid(f"parameter-selector-multi-param"), + "id": self.uuid("parameter-selector-multi-param"), "content": ( "List of parameters. This list is populated only" " if at least one ensemble is selected." @@ -104,11 +105,11 @@ def tour_steps(self) -> List[Dict[str, str]]: ), }, { - "id": self.uuid(f"parameter-deactivator-param"), + "id": self.uuid("parameter-deactivator-param"), "content": "List of currently selected parameters.", }, { - "id": self.uuid(f"parameter-selector-filter-param"), + "id": self.uuid("parameter-selector-filter-param"), "content": ( "Search field. The parameter list will show only" " elements that contain the search characters" diff --git a/webviz_ert/plugins/_response_correlation.py b/webviz_ert/plugins/_response_correlation.py index 31169c78..070e2c0c 100644 --- a/webviz_ert/plugins/_response_correlation.py +++ b/webviz_ert/plugins/_response_correlation.py @@ -1,18 +1,20 @@ +from typing import Dict, List + import dash -import dash_daq -import webviz_ert.assets as assets -import webviz_ert.models -import webviz_ert.controllers import dash_bootstrap_components as dbc +import dash_daq from dash.development.base_component import Component -from typing import List, Dict + +import webviz_ert.controllers +import webviz_ert.models +from webviz_ert import assets +from webviz_ert.models.data_model import DataType +from webviz_ert.plugins import WebvizErtPluginABC from webviz_ert.views import ( - ensemble_selector_list, correlation_view, + ensemble_selector_list, parameter_selector_view, ) -from webviz_ert.models.data_model import DataType -from webviz_ert.plugins import WebvizErtPluginABC class ResponseCorrelation(WebvizErtPluginABC): diff --git a/webviz_ert/plugins/_webviz_ert.py b/webviz_ert/plugins/_webviz_ert.py index 259d1bef..e0835268 100644 --- a/webviz_ert/plugins/_webviz_ert.py +++ b/webviz_ert/plugins/_webviz_ert.py @@ -1,10 +1,12 @@ -from typing import MutableMapping, Optional, Dict, Any +import json +import pathlib +import tempfile +from typing import Any, MutableMapping, Optional + import dash from webviz_config import WebvizPluginABC + from webviz_ert.models import EnsembleModel -import pathlib -import json -import tempfile class WebvizErtPluginABC(WebvizPluginABC): @@ -16,7 +18,7 @@ class WebvizErtPluginABC(WebvizPluginABC): def __init__(self, app: dash.Dash, project_identifier: str): super().__init__() if not project_identifier: - project_identifier = tempfile.NamedTemporaryFile().name + project_identifier = tempfile.NamedTemporaryFile().name # noqa: SIM115 WebvizErtPluginABC._state = {} WebvizErtPluginABC._state_path = None @@ -33,7 +35,7 @@ def init_state(project_root: pathlib.Path) -> MutableMapping[str, Any]: ) if not WebvizErtPluginABC._state_path.exists(): WebvizErtPluginABC._state_path.parent.mkdir(parents=True, exist_ok=True) - return dict() + return {} with open(WebvizErtPluginABC._state_path, "r", encoding="utf-8") as f: return json.load(f) return WebvizErtPluginABC._state diff --git a/webviz_ert/views/__init__.py b/webviz_ert/views/__init__.py index b10d6326..ccad7782 100644 --- a/webviz_ert/views/__init__.py +++ b/webviz_ert/views/__init__.py @@ -1,9 +1,13 @@ -from .parameter_view import parameter_view -from .ensemble_selector_view import ensemble_selector_list -from .response_view import response_view -from .plot_view import plot_view_body, plot_view_header, plot_view_menu -from .misfit_view import response_obs_view -from .parallel_coordinates_view import parallel_coordinates_view -from .selector_view import parameter_selector_view -from .correlation_view import correlation_view -from .element_dropdown_view import element_dropdown_view +from .correlation_view import correlation_view as correlation_view +from .element_dropdown_view import element_dropdown_view as element_dropdown_view +from .ensemble_selector_view import ensemble_selector_list as ensemble_selector_list +from .misfit_view import response_obs_view as response_obs_view +from .parallel_coordinates_view import ( + parallel_coordinates_view as parallel_coordinates_view, +) +from .parameter_view import parameter_view as parameter_view +from .plot_view import plot_view_body as plot_view_body +from .plot_view import plot_view_header as plot_view_header +from .plot_view import plot_view_menu as plot_view_menu +from .response_view import response_view as response_view +from .selector_view import parameter_selector_view as parameter_selector_view diff --git a/webviz_ert/views/correlation_view.py b/webviz_ert/views/correlation_view.py index 9955ebc9..4c9e9a64 100644 --- a/webviz_ert/views/correlation_view.py +++ b/webviz_ert/views/correlation_view.py @@ -1,8 +1,5 @@ +from dash import dcc, html from dash.development.base_component import Component -from webviz_config import WebvizPluginABC - -from dash import html -from dash import dcc def correlation_view(id_view: str) -> Component: diff --git a/webviz_ert/views/element_dropdown_view.py b/webviz_ert/views/element_dropdown_view.py index 7d4e4c61..2fc56dd2 100644 --- a/webviz_ert/views/element_dropdown_view.py +++ b/webviz_ert/views/element_dropdown_view.py @@ -1,8 +1,7 @@ +from dash import dcc, html from dash.development.base_component import Component from webviz_config import WebvizPluginABC -from dash import html -from dash import dcc from webviz_ert.models.data_model import DataType diff --git a/webviz_ert/views/ensemble_selector_view.py b/webviz_ert/views/ensemble_selector_view.py index c8c3997e..8d208898 100644 --- a/webviz_ert/views/ensemble_selector_view.py +++ b/webviz_ert/views/ensemble_selector_view.py @@ -1,11 +1,11 @@ from typing import List -from dash.development.base_component import Component -from webviz_ert.plugins import WebvizErtPluginABC -from dash import html -from dash import dcc -import webviz_core_components as wcc import dash_bootstrap_components as dbc +import webviz_core_components as wcc +from dash import dcc, html +from dash.development.base_component import Component + +from webviz_ert.plugins import WebvizErtPluginABC def ensemble_selector_list(parent: WebvizErtPluginABC) -> List[Component]: diff --git a/webviz_ert/views/misfit_view.py b/webviz_ert/views/misfit_view.py index 88097c5c..0606b5dd 100644 --- a/webviz_ert/views/misfit_view.py +++ b/webviz_ert/views/misfit_view.py @@ -1,10 +1,9 @@ from typing import List -from dash.development.base_component import Component -from webviz_ert.plugins import WebvizErtPluginABC +from dash import dcc, html +from dash.development.base_component import Component -from dash import html -from dash import dcc +from webviz_ert.plugins import WebvizErtPluginABC def response_obs_view(parent: WebvizErtPluginABC) -> List[Component]: diff --git a/webviz_ert/views/parallel_coordinates_view.py b/webviz_ert/views/parallel_coordinates_view.py index 345b805c..13ba00f8 100644 --- a/webviz_ert/views/parallel_coordinates_view.py +++ b/webviz_ert/views/parallel_coordinates_view.py @@ -1,9 +1,6 @@ -from webviz_config import WebvizPluginABC +from dash import dcc, html from dash.development.base_component import Component - -from dash import html -from dash import dcc -import webviz_ert.assets as assets +from webviz_config import WebvizPluginABC def parallel_coordinates_view(parent: WebvizPluginABC) -> Component: diff --git a/webviz_ert/views/parameter_view.py b/webviz_ert/views/parameter_view.py index f9fd09f2..677bd226 100644 --- a/webviz_ert/views/parameter_view.py +++ b/webviz_ert/views/parameter_view.py @@ -1,12 +1,9 @@ from typing import List -from typing import List -from dash.development.base_component import Component -from webviz_config import WebvizPluginABC -from dash import html -from dash import dcc import dash_bootstrap_components as dbc -import webviz_ert.assets as assets +from dash import dcc, html +from dash.development.base_component import Component +from webviz_config import WebvizPluginABC def parameter_view(parent: WebvizPluginABC, index: str = "") -> List[Component]: diff --git a/webviz_ert/views/plot_view.py b/webviz_ert/views/plot_view.py index 55d7cba1..b9848ad2 100644 --- a/webviz_ert/views/plot_view.py +++ b/webviz_ert/views/plot_view.py @@ -1,14 +1,14 @@ from typing import List -from dash.development.base_component import Component -from webviz_ert.plugins import WebvizErtPluginABC -from dash import html -from dash import dcc -import webviz_core_components as wcc import dash_bootstrap_components as dbc -from .selector_view import parameter_selector_view +from dash import dcc, html +from dash.development.base_component import Component + from webviz_ert.models.data_model import DataType +from webviz_ert.plugins import WebvizErtPluginABC + from .ensemble_selector_view import ensemble_selector_list +from .selector_view import parameter_selector_view def plot_view_header(parent: WebvizErtPluginABC) -> List[Component]: diff --git a/webviz_ert/views/response_view.py b/webviz_ert/views/response_view.py index 7804041f..db0a4243 100644 --- a/webviz_ert/views/response_view.py +++ b/webviz_ert/views/response_view.py @@ -1,10 +1,9 @@ from typing import List -from dash.development.base_component import Component -from webviz_config import WebvizPluginABC -from dash import html -from dash import dcc import dash_bootstrap_components as dbc +from dash import dcc, html +from dash.development.base_component import Component +from webviz_config import WebvizPluginABC def response_view(parent: WebvizPluginABC, index: str = "") -> List[Component]: diff --git a/webviz_ert/views/selector_view.py b/webviz_ert/views/selector_view.py index e0c0fe13..fb74ae92 100644 --- a/webviz_ert/views/selector_view.py +++ b/webviz_ert/views/selector_view.py @@ -1,12 +1,10 @@ -from dash.development.base_component import Component -from webviz_ert.plugins import WebvizErtPluginABC - -from dash import html -from dash import dcc -import webviz_core_components as wcc import dash_bootstrap_components as dbc +import webviz_core_components as wcc +from dash import dcc, html +from dash.development.base_component import Component from webviz_ert.models.data_model import DataType +from webviz_ert.plugins import WebvizErtPluginABC def parameter_selector_view(