Skip to content

Commit e39daae

Browse files
authored
Fix logging of missing wildcard rft responses
The logging will now take into account the cases where well, time or both are wildcards ('*')
1 parent 8e32696 commit e39daae

2 files changed

Lines changed: 145 additions & 40 deletions

File tree

src/ert/config/rft_config.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os
77
import re
88
from collections import defaultdict
9+
from copy import copy
910
from dataclasses import InitVar, dataclass
1011
from functools import lru_cache
1112
from pathlib import Path
@@ -289,18 +290,33 @@ def _warn_about_missing_rft_responses(
289290
rft_data: dict[tuple[WellName, datetime.date], RFTConfig.ValidRFTEntry],
290291
rft_filename: str,
291292
) -> None:
292-
well_time_keys = {
293+
well_times = {
293294
(well, time)
294295
for well, time_dict in self.data_to_read.items()
295296
for time in time_dict
296297
}
297-
well_time_keys_rft_data = {(well, time.isoformat()) for well, time in rft_data}
298-
well_time_without_response: set[tuple[str, str]] = (
299-
well_time_keys - well_time_keys_rft_data
300-
)
298+
well_times_with_response = {(well, time.isoformat()) for well, time in rft_data}
299+
300+
well_times_to_warn: set[tuple[str, str]] = well_times - well_times_with_response
301+
302+
# Given well / time wildcard, only warn if there are no responses for
303+
# the corresponding well / time value
304+
wells_with_responses = {well for well, time in well_times_with_response}
305+
times_with_responses = {time for well, time in well_times_with_response}
306+
for well, time in copy(well_times_to_warn):
307+
if well == "*" and time in times_with_responses:
308+
well_times_to_warn.remove((well, time))
309+
if time == "*" and well in wells_with_responses:
310+
well_times_to_warn.remove((well, time))
311+
312+
# Only warn about wildcard well and time if there are no responses
313+
if (wildcard_well_time := ("*", "*")) in well_times and len(
314+
well_times_with_response
315+
) > 0:
316+
well_times_to_warn.remove(wildcard_well_time)
301317

302318
formatted_items = [
303-
f"{well}: {time}" for well, time in sorted(well_time_without_response)
319+
f"{well=} : {time=}" for well, time in sorted(well_times_to_warn)
304320
]
305321
_warn_about_missing_responses(
306322
formatted_items, "well(s) at time(s)", rft_filename

tests/ert/unit_tests/config/test_rft_config.py

Lines changed: 123 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import re
2+
import warnings
23
from datetime import datetime
34
from io import BytesIO
45
from pathlib import Path
@@ -1288,7 +1289,8 @@ def test_that_approximate_missing_rft_values_keyword_sets_interpolation_to_true_
12881289
assert rft_config.approximate_missing_values is expected_setting
12891290

12901291

1291-
def test_that_missing_response_for_rft_well_raises_warning(mock_resfo_file, egrid):
1292+
@pytest.fixture(name="setup_mock_resfo_file")
1293+
def setup_mock_resfo_file(mock_resfo_file, egrid):
12921294
mock_resfo_file(
12931295
"/tmp/does_not_exist/BASE.RFT",
12941296
[
@@ -1309,6 +1311,8 @@ def test_that_missing_response_for_rft_well_raises_warning(mock_resfo_file, egri
13091311
egrid,
13101312
)
13111313

1314+
1315+
def test_that_missing_response_for_rft_well_raises_warning(setup_mock_resfo_file):
13121316
rft_config = RFTConfig(
13131317
input_files=["BASE.RFT"],
13141318
data_to_read={
@@ -1321,29 +1325,14 @@ def test_that_missing_response_for_rft_well_raises_warning(mock_resfo_file, egri
13211325

13221326
expected_warnings = [
13231327
"Could not find responses for well(s) at time(s) in 'BASE.RFT':",
1324-
"NOT_A_WELL: 2000-01-01",
1328+
"well='NOT_A_WELL' : time='2000-01-01'",
13251329
]
13261330
assert any(all(m in str(w) for m in expected_warnings) for w in warnings)
13271331

13281332

13291333
def test_that_one_existing_and_one_missing_rft_response_warns_about_the_one_missing(
1330-
mock_resfo_file, egrid
1334+
setup_mock_resfo_file,
13311335
):
1332-
mock_resfo_file(
1333-
"/tmp/does_not_exist/BASE.RFT",
1334-
[
1335-
*cell_start(date=(1, 1, 2000), well_name="WELL"),
1336-
("PRESSURE", float_arr([100.0, 200.0])),
1337-
("SWAT ", float_arr([0.1, 0.2])),
1338-
("SGAS ", float_arr([0.3, 0.4])),
1339-
("DEPTH ", float_arr([20.0, 30.0])),
1340-
],
1341-
)
1342-
mock_resfo_file(
1343-
"/tmp/does_not_exist/BASE.EGRID",
1344-
egrid,
1345-
)
1346-
13471336
rft_config = RFTConfig(
13481337
input_files=["BASE.RFT"],
13491338
data_to_read={
@@ -1357,26 +1346,12 @@ def test_that_one_existing_and_one_missing_rft_response_warns_about_the_one_miss
13571346
rft_config.read_from_file("/tmp/does_not_exist", 1, 1)
13581347
expected_warnings = [
13591348
"Could not find responses for well(s) at time(s) in 'BASE.RFT':",
1360-
"WELL: 4000-01-01",
1349+
"well='WELL' : time='4000-01-01'",
13611350
]
13621351
assert any(all(m in str(w) for m in expected_warnings) for w in warnings)
13631352

13641353

1365-
def test_that_many_missing_response_warnings_are_truncated(mock_resfo_file, egrid):
1366-
mock_resfo_file(
1367-
"/tmp/does_not_exist/BASE.RFT",
1368-
[
1369-
*cell_start(date=(1, 1, 2000), well_name="WELL"),
1370-
("PRESSURE", float_arr([100.0, 200.0])),
1371-
("SWAT ", float_arr([0.1, 0.2])),
1372-
("SGAS ", float_arr([0.3, 0.4])),
1373-
("DEPTH ", float_arr([20.0, 30.0])),
1374-
],
1375-
)
1376-
mock_resfo_file(
1377-
"/tmp/does_not_exist/BASE.EGRID",
1378-
egrid,
1379-
)
1354+
def test_that_many_missing_response_warnings_are_truncated(setup_mock_resfo_file):
13801355
num_missing_responses = 9
13811356
rft_config = RFTConfig(
13821357
input_files=["BASE.RFT"],
@@ -1400,3 +1375,117 @@ def test_that_many_missing_response_warnings_are_truncated(mock_resfo_file, egri
14001375
match = re.search(r"and (\d+) other missing responses", last_line)
14011376
excess_warnings = int(match.group(1))
14021377
assert excess_warnings == num_missing_responses - _RESPONSE_WARNING_LIMIT
1378+
1379+
1380+
def test_that_wildcard_wells_are_not_warned_about(setup_mock_resfo_file):
1381+
rft_config = RFTConfig(
1382+
input_files=["BASE.RFT"],
1383+
data_to_read={
1384+
"*": {"2000-01-01": ["PRESSURE", "SWAT"]},
1385+
},
1386+
)
1387+
with warnings.catch_warnings():
1388+
warnings.simplefilter( # Asserts no PostExperimentWarnings were raised
1389+
"error", PostExperimentWarning
1390+
)
1391+
rft_config.read_from_file("/tmp/does_not_exist", 1, 1)
1392+
1393+
1394+
def test_that_wildcard_times_are_not_warned_about_given_any_well_response(
1395+
setup_mock_resfo_file,
1396+
):
1397+
rft_config = RFTConfig(
1398+
input_files=["BASE.RFT"],
1399+
data_to_read={
1400+
"WELL": {"*": ["PRESSURE", "SWAT"]},
1401+
},
1402+
)
1403+
with warnings.catch_warnings():
1404+
warnings.simplefilter( # Asserts no PostExperimentWarnings were raised
1405+
"error", PostExperimentWarning
1406+
)
1407+
rft_config.read_from_file("/tmp/does_not_exist", 1, 1)
1408+
1409+
1410+
def test_that_wildcard_times_are_warned_about_given_no_well_response(
1411+
setup_mock_resfo_file,
1412+
):
1413+
rft_config = RFTConfig(
1414+
input_files=["BASE.RFT"],
1415+
data_to_read={
1416+
"DIFFERENT_WELL": {"*": ["PRESSURE", "SWAT"]},
1417+
},
1418+
)
1419+
with pytest.warns(PostExperimentWarning) as warnings:
1420+
rft_config.read_from_file("/tmp/does_not_exist", 1, 1)
1421+
1422+
expected_warnings = [
1423+
"Could not find responses for well(s) at time(s)",
1424+
"well='DIFFERENT_WELL' : time='*'",
1425+
]
1426+
# Assert one warning contains all expected warnings
1427+
assert any(all(e_w in str(w) for e_w in expected_warnings) for w in warnings)
1428+
1429+
1430+
def test_that_wildcard_wells_are_warned_about_given_no_time_response(
1431+
setup_mock_resfo_file,
1432+
):
1433+
rft_config = RFTConfig(
1434+
input_files=["BASE.RFT"],
1435+
data_to_read={
1436+
"*": {"2010-10-10": ["PRESSURE", "SWAT"]},
1437+
},
1438+
)
1439+
with pytest.warns(PostExperimentWarning) as warnings:
1440+
rft_config.read_from_file("/tmp/does_not_exist", 1, 1)
1441+
1442+
expected_warnings = [
1443+
"Could not find responses for well(s) at time(s)",
1444+
"well='*' : time='2010-10-10'",
1445+
]
1446+
# Assert one warning contains all expected warnings
1447+
assert any(all(e_w in str(w) for e_w in expected_warnings) for w in warnings)
1448+
1449+
1450+
def test_that_wildcard_well_with_wildcard_time_without_any_response_is_warned_about(
1451+
mock_resfo_file, egrid
1452+
):
1453+
mock_resfo_file(
1454+
"/tmp/does_not_exist/BASE.RFT",
1455+
[],
1456+
)
1457+
mock_resfo_file(
1458+
"/tmp/does_not_exist/BASE.EGRID",
1459+
egrid,
1460+
)
1461+
rft_config = RFTConfig(
1462+
input_files=["BASE.RFT"],
1463+
data_to_read={
1464+
"*": {"*": ["PRESSURE", "SWAT"]},
1465+
},
1466+
)
1467+
with pytest.warns(PostExperimentWarning) as warnings:
1468+
rft_config.read_from_file("/tmp/does_not_exist", 1, 1)
1469+
1470+
expected_warnings = [
1471+
"Could not find responses for well(s) at time(s)",
1472+
"well='*' : time='*'",
1473+
]
1474+
# Assert one warning contains all expected warnings
1475+
assert any(all(e_w in str(w) for e_w in expected_warnings) for w in warnings)
1476+
1477+
1478+
def test_that_wildcard_well_with_wildcard_time_with_any_response_is_not_warned_about(
1479+
setup_mock_resfo_file,
1480+
):
1481+
rft_config = RFTConfig(
1482+
input_files=["BASE.RFT"],
1483+
data_to_read={
1484+
"*": {"*": ["PRESSURE", "SWAT"]},
1485+
},
1486+
)
1487+
with warnings.catch_warnings():
1488+
warnings.simplefilter( # Asserts no PostExperimentWarnings were raised
1489+
"error", PostExperimentWarning
1490+
)
1491+
rft_config.read_from_file("/tmp/does_not_exist", 1, 1)

0 commit comments

Comments
 (0)