Skip to content

Commit

Permalink
Simplify LibresFacade
Browse files Browse the repository at this point in the history
  • Loading branch information
oyvindeide committed Nov 28, 2024
1 parent 68c2de9 commit b684887
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 88 deletions.
4 changes: 2 additions & 2 deletions src/ert/config/gen_data_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ def from_config_dict(cls, config_dict: ConfigDict) -> Optional[Self]:
def read_from_file(self, run_path: str, iens: int, iter: int) -> polars.DataFrame:
def _read_file(filename: Path, report_step: int) -> polars.DataFrame:
try:
data = np.loadtxt(_run_path / filename, ndmin=1)
data = np.loadtxt(filename, ndmin=1)
except ValueError as err:
raise InvalidResponseFile(str(err)) from err
active_information_file = _run_path / (str(filename) + "_active")
active_information_file = filename.parent / (filename.name + "_active")
if active_information_file.exists():
try:
active_list = np.loadtxt(active_information_file)
Expand Down
20 changes: 0 additions & 20 deletions src/ert/libres_facade.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import asyncio
import logging
import time
import warnings
from multiprocessing.pool import ThreadPool
from pathlib import Path
Expand Down Expand Up @@ -36,8 +35,6 @@
_logger = logging.getLogger(__name__)

if TYPE_CHECKING:
import numpy.typing as npt

from ert.config import (
EnkfObs,
WorkflowJob,
Expand Down Expand Up @@ -125,23 +122,6 @@ def run_path(self) -> str:
def resolved_run_path(self) -> str:
return str(Path(self.config.model_config.runpath_format_string).resolve())

def load_from_forward_model(
self,
ensemble: Ensemble,
realisations: npt.NDArray[np.bool_],
) -> int:
t = time.perf_counter()
nr_loaded = self.load_from_run_path(
self.resolved_run_path,
ensemble,
[r for r, active in enumerate(realisations) if active],
)
ensemble.refresh_ensemble_state()
_logger.debug(
f"load_from_forward_model() time_used {(time.perf_counter() - t):.4f}s"
)
return nr_loaded

@staticmethod
def load_from_run_path(
run_path_format: str,
Expand Down
22 changes: 4 additions & 18 deletions tests/ert/performance_tests/enkf/test_load_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,14 @@ def test_load_from_context(benchmark, template_config):

with path.as_cwd(), open_storage(path / "_storage", mode="w") as storage:
config = ErtConfig.from_file("poly.ert")
facade = LibresFacade.from_config_file("poly.ert")
load_into = storage.create_experiment().create_ensemble(
name="A1", ensemble_size=config.model_config.num_realizations
)
expected_reals = template_config["reals"]
realisations = [True] * expected_reals
loaded_reals = benchmark(
facade.load_from_forward_model, load_into, realisations
)
assert loaded_reals == expected_reals


def test_load_from_fs(benchmark, template_config):
path = template_config["folder"]

with path.as_cwd(), open_storage(path / "storage", mode="w") as storage:
facade = LibresFacade.from_config_file("poly.ert")
experiment = storage.get_experiment_by_name("ensemble-experiment")
load_from = experiment.get_ensemble_by_name("default")
expected_reals = template_config["reals"]
realisations = [True] * expected_reals
loaded_reals = benchmark(
facade.load_from_forward_model, load_from, realisations
LibresFacade.load_from_run_path,
config.model_config.runpath_format_string,
load_into,
list(range(expected_reals)),
)
assert loaded_reals == expected_reals
7 changes: 0 additions & 7 deletions tests/ert/ui_tests/cli/test_parameter_sample_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,12 @@
import pytest
import xtgeo

from ert.libres_facade import LibresFacade
from ert.mode_definitions import ENSEMBLE_SMOOTHER_MODE
from ert.storage import open_storage

from .run_cli import run_cli


def load_from_forward_model(ert_config, ensemble):
facade = LibresFacade.from_config_file(ert_config)
realizations = [True] * facade.get_ensemble_size()
return facade.load_from_forward_model(ensemble, realizations)


@pytest.mark.usefixtures("set_site_config")
def test_surface_param_update(tmpdir):
"""Full update with a surface parameter, it mirrors the poly example,
Expand Down
20 changes: 10 additions & 10 deletions tests/ert/unit_tests/scenarios/test_summary_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,24 +66,25 @@ def ert_config(tmpdir):
yield ErtConfig.from_file("config.ert")


def create_responses(config_file, prior_ensemble, response_times):
def create_responses(prior_ensemble, response_times):
cwd = Path().absolute()
rng = np.random.default_rng(seed=1234)
base_path = cwd / "simulations" / "realization-<IENS>" / "iter-0"
for i, response_time in enumerate(response_times):
sim_path = cwd / "simulations" / f"realization-{i}" / "iter-0"
sim_path = Path(str(base_path).replace("<IENS>", str(i)))
sim_path.mkdir(parents=True, exist_ok=True)
os.chdir(sim_path)
run_sim(response_time, rng.standard_normal(), fname=f"ECLIPSE_CASE_{i}")
os.chdir(cwd)
facade = LibresFacade.from_config_file(config_file)
facade.load_from_forward_model(prior_ensemble, [True] * facade.get_ensemble_size())
LibresFacade.load_from_run_path(
str(base_path), prior_ensemble, range(len(response_times))
)


def test_that_reading_matching_time_is_ok(ert_config, storage, prior_ensemble):
sample_prior(prior_ensemble, range(prior_ensemble.ensemble_size))

create_responses(
ert_config.user_config_file,
prior_ensemble,
ert_config.model_config.num_realizations * [[datetime(2014, 9, 9)]],
)
Expand Down Expand Up @@ -112,7 +113,7 @@ def test_that_mismatched_responses_give_error(ert_config, storage, prior_ensembl
[datetime(2014, 9, 9)],
[datetime(2017, 9, 9)],
]
create_responses(ert_config.user_config_file, prior_ensemble, response_times)
create_responses(prior_ensemble, response_times)

target_ensemble = storage.create_ensemble(
prior_ensemble.experiment_id,
Expand Down Expand Up @@ -144,7 +145,7 @@ def test_that_different_length_is_ok_as_long_as_observation_time_exists(
[datetime(2014, 9, 9)],
[datetime(2014, 9, 9), datetime(1988, 9, 9)],
]
create_responses(ert_config.user_config_file, prior_ensemble, response_times)
create_responses(prior_ensemble, response_times)

target_ensemble = storage.create_ensemble(
prior_ensemble.experiment_id,
Expand Down Expand Up @@ -190,7 +191,7 @@ def test_that_duplicate_summary_time_steps_does_not_fail(
[datetime(2014, 9, 9)],
[datetime(2014, 9, 9), datetime(1988, 9, 9)],
]
create_responses(ert_config.user_config_file, prior_ensemble, response_times)
create_responses(prior_ensemble, response_times)

target_ensemble = storage.create_ensemble(
prior_ensemble.experiment_id,
Expand All @@ -216,7 +217,7 @@ def test_that_mismatched_responses_gives_nan_measured_data(ert_config, prior_ens
[datetime(2014, 9, 9)],
[datetime(2017, 9, 9)],
]
create_responses(ert_config.user_config_file, prior_ensemble, response_times)
create_responses(prior_ensemble, response_times)

measured_data = MeasuredData(prior_ensemble)

Expand All @@ -240,7 +241,6 @@ def test_reading_past_2263_is_ok(ert_config, storage, prior_ensemble):
sample_prior(prior_ensemble, range(prior_ensemble.ensemble_size))

create_responses(
ert_config.user_config_file,
prior_ensemble,
ert_config.model_config.num_realizations * [[datetime(2500, 9, 9)]],
)
Expand Down
7 changes: 0 additions & 7 deletions tests/ert/unit_tests/storage/create_runpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from ert.config import ErtConfig
from ert.enkf_main import create_run_path, sample_prior
from ert.libres_facade import LibresFacade
from ert.run_arg import create_run_arguments
from ert.runpaths import Runpaths
from ert.storage import Ensemble
Expand Down Expand Up @@ -57,9 +56,3 @@ def create_runpath(
runpaths=runpaths,
)
return ert_config.ensemble_config, ensemble


def load_from_forward_model(ert_config, ensemble):
facade = LibresFacade.from_config_file(ert_config)
realizations = [True] * facade.get_ensemble_size()
return facade.load_from_forward_model(ensemble, realizations)
10 changes: 8 additions & 2 deletions tests/ert/unit_tests/storage/test_parameter_sample_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
import pytest
from resdata.geometry import Surface

from ert import LibresFacade
from ert.config import ConfigValidationError, ErtConfig, GenKwConfig
from ert.config.gen_kw_config import TransformFunctionDefinition
from ert.enkf_main import sample_prior
from ert.storage import open_storage

from .create_runpath import create_runpath, load_from_forward_model
from .create_runpath import create_runpath


@pytest.fixture
Expand Down Expand Up @@ -94,7 +95,12 @@ def test_surface_param(
assert ensemble_config["MY_PARAM"].forward_init is expect_forward_init
# We try to load the parameters from the forward model, this would fail if
# forward init was not set correctly
assert load_from_forward_model("config.ert", fs) == expect_num_loaded
assert (
LibresFacade.load_from_run_path(
"simulations/realization-<IENS>/iter-0", fs, [0]
)
== expect_num_loaded
)
assert error in "".join(caplog.messages)

# Assert that the data has been written to runpath
Expand Down
39 changes: 19 additions & 20 deletions tests/ert/unit_tests/test_load_forward_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def func(config_text):
model_config=ert_config.model_config,
runpaths=run_paths(ert_config),
)
return ert_config, prior_ensemble
return prior_ensemble

yield func

Expand Down Expand Up @@ -75,15 +75,16 @@ def test_load_forward_model(snake_oil_default_storage):
facade = LibresFacade.from_config_file("snake_oil.ert")
realisation_number = 0

realizations = [False] * facade.get_ensemble_size()
realizations[realisation_number] = True

with open_storage(facade.enspath, mode="w") as storage:
# 'load_from_forward_model' requires the ensemble to be writeable...
experiment = storage.get_experiment_by_name("ensemble-experiment")
default = experiment.get_ensemble_by_name("default_0")

loaded = facade.load_from_forward_model(default, realizations)
loaded = LibresFacade.load_from_run_path(
"storage/snake_oil/runpath/realization-<IENS>/iter-<ITER>",
default,
[realisation_number],
)
assert loaded == 1
assert default.get_realization_mask_with_responses()[
realisation_number
Expand Down Expand Up @@ -151,9 +152,10 @@ def test_load_forward_model_summary(
model_config=ert_config.model_config,
runpaths=run_paths(ert_config),
)
facade = LibresFacade(ert_config)
with caplog.at_level(logging.ERROR):
loaded = facade.load_from_forward_model(prior_ensemble, [True])
loaded = LibresFacade.load_from_run_path(
ert_config.model_config.runpath_format_string, prior_ensemble, [0]
)
expected_loaded, expected_log_message = expected
assert loaded == expected_loaded
if expected_log_message:
Expand All @@ -168,7 +170,7 @@ def test_load_forward_model_gen_data(setup_case):
"""
)

config, prior_ensemble = setup_case(config_text)
prior_ensemble = setup_case(config_text)
run_path = Path("simulations/realization-0/iter-0/")
with open(run_path / "response_0.out", "w", encoding="utf-8") as fout:
fout.write("\n".join(["1", "2", "3"]))
Expand All @@ -177,8 +179,7 @@ def test_load_forward_model_gen_data(setup_case):
with open(run_path / "response_0.out_active", "w", encoding="utf-8") as fout:
fout.write("\n".join(["1", "0", "1"]))

facade = LibresFacade(config)
facade.load_from_forward_model(prior_ensemble, [True])
LibresFacade.load_from_run_path(str(run_path), prior_ensemble, [0])
df = prior_ensemble.load_responses("gen_data", (0,))
filter_cond = polars.col("report_step").eq(0), polars.col("values").is_not_nan()
assert df.filter(filter_cond)["values"].to_list() == [1.0, 3.0]
Expand All @@ -191,16 +192,15 @@ def test_single_valued_gen_data_with_active_info_is_loaded(setup_case):
GEN_DATA RESPONSE RESULT_FILE:response_%d.out REPORT_STEPS:0 INPUT_FORMAT:ASCII
"""
)
config, prior_ensemble = setup_case(config_text)
prior_ensemble = setup_case(config_text)

run_path = Path("simulations/realization-0/iter-0/")
with open(run_path / "response_0.out", "w", encoding="utf-8") as fout:
fout.write("\n".join(["1"]))
with open(run_path / "response_0.out_active", "w", encoding="utf-8") as fout:
fout.write("\n".join(["1"]))

facade = LibresFacade(config)
facade.load_from_forward_model(prior_ensemble, [True])
LibresFacade.load_from_run_path(str(run_path), prior_ensemble, [0])
df = prior_ensemble.load_responses("RESPONSE", (0,))
assert df["values"].to_list() == [1.0]

Expand All @@ -212,16 +212,15 @@ def test_that_all_deactivated_values_are_loaded(setup_case):
GEN_DATA RESPONSE RESULT_FILE:response_%d.out REPORT_STEPS:0 INPUT_FORMAT:ASCII
"""
)
config, prior_ensemble = setup_case(config_text)
prior_ensemble = setup_case(config_text)

run_path = Path("simulations/realization-0/iter-0/")
with open(run_path / "response_0.out", "w", encoding="utf-8") as fout:
fout.write("\n".join(["-1"]))
with open(run_path / "response_0.out_active", "w", encoding="utf-8") as fout:
fout.write("\n".join(["0"]))

facade = LibresFacade(config)
facade.load_from_forward_model(prior_ensemble, [True])
LibresFacade.load_from_run_path(str(run_path), prior_ensemble, [0])
response = prior_ensemble.load_responses("RESPONSE", (0,))
assert np.isnan(response[0]["values"].to_list())
assert len(response) == 1
Expand Down Expand Up @@ -264,8 +263,7 @@ def test_loading_gen_data_without_restart(storage, run_paths, run_args):
with open(run_path / "response.out_active", "w", encoding="utf-8") as fout:
fout.write("\n".join(["1", "0", "1"]))

facade = LibresFacade.from_config_file("config.ert")
facade.load_from_forward_model(prior_ensemble, [True])
LibresFacade.load_from_run_path(str(run_path), prior_ensemble, [0])
df = prior_ensemble.load_responses("RESPONSE", (0,))
df_no_nans = df.filter(polars.col("values").is_not_nan())
assert df_no_nans["values"].to_list() == [1.0, 3.0]
Expand All @@ -282,12 +280,13 @@ def test_that_the_states_are_set_correctly():
experiment = storage.get_experiment_by_name("ensemble-experiment")
ensemble = experiment.get_ensemble_by_name("default_0")
ensemble_size = facade.get_ensemble_size()
realizations = np.array([True] * ensemble_size)

new_ensemble = storage.create_ensemble(
experiment=ensemble.experiment, ensemble_size=ensemble_size
)
facade.load_from_forward_model(new_ensemble, realizations)
LibresFacade.load_from_run_path(
facade.run_path, new_ensemble, list(range(ensemble_size))
)
assert not new_ensemble.is_initalized()
assert new_ensemble.has_data()

Expand Down
5 changes: 3 additions & 2 deletions tests/ert/unit_tests/test_summary_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ def test_load_summary_response_restart_not_zero(
shutil.copy(test_path / "PRED_RUN.SMSPEC", sim_path / "PRED_RUN.SMSPEC")
shutil.copy(test_path / "PRED_RUN.UNSMRY", sim_path / "PRED_RUN.UNSMRY")

facade = LibresFacade.from_config_file("config.ert")
facade.load_from_forward_model(ensemble, [True])
LibresFacade.load_from_run_path(
ert_config.model_config.runpath_format_string, ensemble, [0]
)

df = ensemble.load_responses("summary", (0,))
df = df.pivot(on="response_key", values="values")
Expand Down

0 comments on commit b684887

Please sign in to comment.