Skip to content

Commit 8ef23c3

Browse files
committed
fixup! Support parquet observation files in SeismicObservation
1 parent b5c03a7 commit 8ef23c3

4 files changed

Lines changed: 54 additions & 32 deletions

File tree

src/ert/config/_observations.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,9 +1076,9 @@ def from_obs_dict(
10761076
) -> list[Self]:
10771077
"""Create seismic observations from an observation dictionary.
10781078
1079-
File containing seismic observations (CSV) and file containing the polygon
1080-
limiting observations used in the match step (BOUNDARY) are specified relative
1081-
to the directory of the observation config.
1079+
File containing seismic observations (CSV or Parquet) and file containing the
1080+
polygon limiting observations used in the match step (BOUNDARY) are specified
1081+
relative to the directory of the observation config.
10821082
10831083
Args:
10841084
directory: Directory where observation config is located.
@@ -1088,6 +1088,13 @@ def from_obs_dict(
10881088
name = ""
10891089
filepath: str | Path | None = None
10901090
boundary_filepath: str | Path | None = None
1091+
1092+
if "CSV" in observation_dict and "OBS_FILE" in observation_dict:
1093+
raise ObservationConfigError.with_context(
1094+
"SEISMIC_OBSERVATION cannot contain both 'CSV' and 'OBS_FILE'.",
1095+
observation_dict.context,
1096+
)
1097+
10911098
for key, value in observation_dict.items():
10921099
match key:
10931100
case "type":
@@ -1097,7 +1104,8 @@ def from_obs_dict(
10971104
case "CSV":
10981105
ConfigWarning.warn(
10991106
"CSV key is deprecated for seismic observations. "
1100-
"Use OBS_FILE instead. "
1107+
"Use OBS_FILE instead.",
1108+
observation_dict.context,
11011109
)
11021110
filepath = value
11031111
case "OBS_FILE":
@@ -1107,19 +1115,13 @@ def from_obs_dict(
11071115
case _:
11081116
raise _unknown_key_error(str(key), observation_dict.context)
11091117

1110-
if "CSV" in observation_dict and "OBS_FILE" in observation_dict:
1111-
raise ObservationConfigError.with_context(
1112-
"SEISMIC_OBSERVATION cannot contain both 'CSV' and 'OBS_FILE'.",
1113-
observation_dict.context,
1114-
)
1115-
11161118
if filepath is None:
11171119
raise _missing_value_error(observation_dict.context, "OBS_FILE")
11181120

11191121
filepath = Path(directory) / filepath
11201122
if not filepath.exists():
11211123
raise ObservationConfigError.with_context(
1122-
f"The CSV file ({filepath.absolute()}) "
1124+
f"The seismic observations file ({filepath.absolute()}) "
11231125
"does not exist or is not accessible.",
11241126
filepath,
11251127
)

tests/ert/defaults_generator.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import numpy as np
55
import polars as pl
6+
from lark import Token
67

78
from ert.config._observations import (
89
BreakthroughObservation,
@@ -11,7 +12,8 @@
1112
SeismicObservation,
1213
SummaryObservation,
1314
)
14-
from ert.config.parsing.observations_parser import ObservationType
15+
from ert.config.parsing.file_context_token import FileContextToken
16+
from ert.config.parsing.observations_parser import ObservationDict, ObservationType
1517
from ert.config.seismic_config import SeismicConfig
1618

1719

@@ -208,13 +210,23 @@ def create_seismic_observation_dict(
208210
name: str = "seismic_observation",
209211
csv: str = "horizon--amplitude_full_min_depth--20250101_20240101.csv",
210212
obs_file: str | None = None,
211-
) -> dict:
212-
result = {"type": ObservationType.SEISMIC, "name": name}
213+
) -> ObservationDict:
214+
data: dict = {"type": ObservationType.SEISMIC, "name": name}
213215
if obs_file is not None:
214-
result["OBS_FILE"] = obs_file
216+
data["OBS_FILE"] = obs_file
215217
else:
216-
result["CSV"] = csv
217-
return result
218+
data["CSV"] = csv
219+
context = FileContextToken(
220+
Token(
221+
type="foo",
222+
line=2,
223+
column=5,
224+
end_column=13,
225+
value="SEISMIC_OBSERVATION",
226+
),
227+
"observations.txt",
228+
)
229+
return ObservationDict(data, context=context)
218230

219231

220232
def create_seismic_response(

tests/ert/unit_tests/config/test_observation_declaration.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ def test_that_non_existent_seismic_observation_file_raises_error(file_context_to
884884
)
885885

886886

887-
def test_that_missing_seismic_csv_filename_raises_error(file_context_token):
887+
def test_that_missing_seismic_observation_filename_raises_error(file_context_token):
888888
with pytest.raises(ObservationConfigError) as err:
889889
make_observations(
890890
"",
@@ -971,7 +971,13 @@ def test_that_missing_columns_in_seismic_parquet_observation_file_raises(
971971
}
972972
).write_parquet("seismic_observations.parquet")
973973

974-
with pytest.raises(ObservationConfigError) as err:
974+
with pytest.raises(
975+
ObservationConfigError,
976+
match=(
977+
r"The seismic observations file seismic_observations.parquet "
978+
r"is missing required column\(s\) X_UTME, Y_UTMN."
979+
),
980+
):
975981
make_observations(
976982
"",
977983
[
@@ -986,10 +992,6 @@ def test_that_missing_columns_in_seismic_parquet_observation_file_raises(
986992
],
987993
shape_registry=ShapeRegistry(),
988994
)
989-
assert (
990-
"The seismic observations file seismic_observations.parquet "
991-
"is missing required column(s) X_UTME, Y_UTMN." in str(err.value)
992-
)
993995

994996

995997
@pytest.mark.usefixtures("use_tmpdir")

tests/ert/unit_tests/config/test_observations.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2466,8 +2466,9 @@ def test_that_seismic_observation_dataframes_are_created_deprecated_csv_key(
24662466
)
24672467

24682468

2469-
def test_that_seismic_observation_dataframes_are_created_from_parquet_file(
2470-
mocked_files, file_context_token
2469+
@pytest.mark.parametrize("file_format", ["parquet", "csv"])
2470+
def test_that_seismic_observation_dataframes_are_created_from_obs_file(
2471+
mocked_files, file_context_token, file_format
24712472
):
24722473
frame1 = pl.DataFrame(
24732474
{
@@ -2488,11 +2489,16 @@ def test_that_seismic_observation_dataframes_are_created_from_parquet_file(
24882489
}
24892490
)
24902491

2491-
buf1, buf2 = BytesIO(), BytesIO()
2492-
frame1.write_parquet(buf1)
2493-
frame2.write_parquet(buf2)
2494-
mocked_files["obs1.parquet"] = buf1.getvalue()
2495-
mocked_files["obs2.parquet"] = buf2.getvalue()
2492+
if file_format == "parquet":
2493+
buf1, buf2 = BytesIO(), BytesIO()
2494+
frame1.write_parquet(buf1)
2495+
frame2.write_parquet(buf2)
2496+
mocked_files["obs1.parquet"] = buf1.getvalue()
2497+
mocked_files["obs2.parquet"] = buf2.getvalue()
2498+
else:
2499+
mocked_files["obs1.csv"] = frame1.write_csv()
2500+
mocked_files["obs2.csv"] = frame2.write_csv()
2501+
24962502
ert_config = ErtConfig.from_dict(
24972503
{
24982504
"OBS_CONFIG": (
@@ -2502,15 +2508,15 @@ def test_that_seismic_observation_dataframes_are_created_from_parquet_file(
25022508
{
25032509
"type": ObservationType.SEISMIC,
25042510
"name": "NAME1",
2505-
"OBS_FILE": "obs1.parquet",
2511+
"OBS_FILE": f"obs1.{file_format}",
25062512
},
25072513
context=file_context_token(obs_type="SEISMIC_OBSERVATION"),
25082514
),
25092515
ObservationDict(
25102516
{
25112517
"type": ObservationType.SEISMIC,
25122518
"name": None,
2513-
"OBS_FILE": "obs2.parquet",
2519+
"OBS_FILE": f"obs2.{file_format}",
25142520
},
25152521
context=file_context_token(obs_type="SEISMIC_OBSERVATION"),
25162522
),

0 commit comments

Comments
 (0)