mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
- Return std::expected from RimSurfaceCollection::importSurfacesFromFiles with a message naming the files that could not be imported - Return specific errors from ImportSurface and NewSurface scripting methods instead of nullptr - Import before deleting the surface to overwrite, so a failed overwrite keeps the existing surface - Catch surfio exceptions in RifSurfio to avoid a crash on corrupt files - Include the method name in the generic "no result" gRPC error - Add Python tests for import_surface error handling
286 lines
11 KiB
Python
286 lines
11 KiB
Python
import sys
|
|
import os
|
|
import tempfile
|
|
import pytest
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(1, os.path.join(sys.path[0], "../../"))
|
|
import rips
|
|
|
|
import dataroot
|
|
|
|
|
|
def test_create_and_export_surface(rips_instance, initialize_test):
|
|
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID"
|
|
case = rips_instance.project.load_case(path=case_path)
|
|
assert len(case.grids()) == 1
|
|
|
|
surface_collection = rips_instance.project.descendants(rips.SurfaceCollection)[0]
|
|
|
|
surface = surface_collection.new_surface(case, 5)
|
|
assert surface
|
|
|
|
with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
|
|
path = Path(tmpdirname, "mysurface.ts")
|
|
print("Temporary folder: ", path.as_posix())
|
|
|
|
surface.export_to_file(path.as_posix())
|
|
|
|
assert path.exists()
|
|
|
|
|
|
def test_create_regular_surface(rips_instance, initialize_test):
|
|
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID"
|
|
c = rips_instance.project.load_case(path=case_path)
|
|
assert len(c.grids()) == 1
|
|
|
|
surface_collection = rips_instance.project.descendants(rips.SurfaceCollection)[0]
|
|
|
|
bbox = c.reservoir_boundingbox()
|
|
depth = bbox.max_z - ((bbox.max_z - bbox.min_z) / 2.0)
|
|
|
|
origin_x = bbox.min_x
|
|
origin_y = bbox.min_y
|
|
name = "test surface name"
|
|
nx = 20
|
|
ny = 10
|
|
increment_x = (bbox.max_x - bbox.min_x) / float(nx)
|
|
increment_y = (bbox.max_y - bbox.min_y) / float(ny)
|
|
rotation = 23.4
|
|
|
|
s = surface_collection.new_regular_surface(
|
|
name=name,
|
|
origin_x=origin_x,
|
|
origin_y=origin_y,
|
|
depth=-depth,
|
|
nx=nx,
|
|
ny=ny,
|
|
increment_x=increment_x,
|
|
increment_y=increment_y,
|
|
rotation=rotation,
|
|
)
|
|
|
|
assert s.origin_x == origin_x
|
|
assert s.origin_y == origin_y
|
|
assert s.increment_x == increment_x
|
|
assert s.increment_y == increment_y
|
|
assert s.rotation == rotation
|
|
assert s.nx == nx
|
|
assert s.ny == ny
|
|
|
|
with pytest.raises(
|
|
rips.RipsError, match="Failed to set property: incorrect dimensions."
|
|
):
|
|
s.set_property("property_too_big", [i for i in range(nx * ny * 2)])
|
|
|
|
# Successfully set the depth property
|
|
s.set_property("depth", [i for i in range(nx * ny)])
|
|
s.set_property_as_depth("depth")
|
|
|
|
# Change the dimensions of the surface: should invalidate the properties
|
|
s.nx = 30
|
|
s.update()
|
|
|
|
|
|
def test_surface_settings_in_view(rips_instance, initialize_test):
|
|
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID"
|
|
case = rips_instance.project.load_case(path=case_path)
|
|
|
|
surface_collection = rips_instance.project.descendants(rips.SurfaceCollection)[0]
|
|
folder = surface_collection.add_folder(folder_name="View surfaces")
|
|
surface = folder.new_regular_surface(name="View surface", nx=2, ny=2)
|
|
surface.set_property("Property A", [1.0, 2.0, 3.0, 4.0])
|
|
surface.set_property("Property B", [5.0, 6.0, 7.0, 8.0])
|
|
|
|
first_view = case.create_view()
|
|
second_view = case.create_view()
|
|
|
|
assert first_view.set_surface_visible(surface=surface, visible=False) is None
|
|
assert second_view.set_surface_visible(surface=surface, visible=True) is None
|
|
assert (
|
|
first_view.set_surface_property(surface=surface, property_name="Property B")
|
|
is None
|
|
)
|
|
|
|
with pytest.raises(rips.RipsError, match="not available for surface"):
|
|
first_view.set_surface_property(surface=surface, property_name="Missing")
|
|
|
|
with pytest.raises(rips.RipsError, match="Surface is null"):
|
|
first_view.set_surface_visible(surface=None, visible=True)
|
|
|
|
|
|
def test_get_property(rips_instance, initialize_test):
|
|
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID"
|
|
c = rips_instance.project.load_case(path=case_path)
|
|
assert len(c.grids()) == 1
|
|
|
|
surface_collection = rips_instance.project.descendants(rips.SurfaceCollection)[0]
|
|
|
|
nx = 5
|
|
ny = 4
|
|
s = surface_collection.new_regular_surface(nx=nx, ny=ny)
|
|
|
|
input_values = [float(i) for i in range(nx * ny)]
|
|
s.set_property("test_prop", input_values)
|
|
|
|
output_values = s.get_property("test_prop")
|
|
assert len(output_values) == nx * ny
|
|
for i in range(len(input_values)):
|
|
assert abs(output_values[i] - input_values[i]) < 1e-6
|
|
|
|
# Getting a non-existent property should raise an error
|
|
with pytest.raises(rips.RipsError, match="not found"):
|
|
s.get_property("non_existent_property")
|
|
|
|
|
|
def test_available_properties(rips_instance, initialize_test):
|
|
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID"
|
|
c = rips_instance.project.load_case(path=case_path)
|
|
assert len(c.grids()) == 1
|
|
|
|
surface_collection = rips_instance.project.descendants(rips.SurfaceCollection)[0]
|
|
|
|
nx = 5
|
|
ny = 4
|
|
s = surface_collection.new_regular_surface(nx=nx, ny=ny)
|
|
|
|
# Empty property list initially
|
|
props = s.available_properties()
|
|
assert props == []
|
|
|
|
# Property names after setting one property
|
|
s.set_property("prop_a", [float(i) for i in range(nx * ny)])
|
|
props = s.available_properties()
|
|
assert "prop_a" in props
|
|
assert len(props) == 1
|
|
|
|
# Property names persist after setting multiple properties
|
|
s.set_property("prop_b", [float(i) for i in range(nx * ny)])
|
|
props = s.available_properties()
|
|
assert len(props) == 2
|
|
assert "prop_a" in props
|
|
assert "prop_b" in props
|
|
|
|
|
|
def test_create_regular_surface_invalid_values(rips_instance, initialize_test):
|
|
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID"
|
|
c = rips_instance.project.load_case(path=case_path)
|
|
assert len(c.grids()) == 1
|
|
|
|
surface_collection = rips_instance.project.descendants(rips.SurfaceCollection)[0]
|
|
|
|
with pytest.raises(rips.RipsError, match="Invalid nx"):
|
|
surface_collection.new_regular_surface(nx=-1)
|
|
|
|
with pytest.raises(rips.RipsError, match="Invalid ny"):
|
|
surface_collection.new_regular_surface(ny=-1)
|
|
|
|
with pytest.raises(rips.RipsError, match="Invalid increment X. Must be positive."):
|
|
surface_collection.new_regular_surface(increment_x=-1.0)
|
|
|
|
with pytest.raises(rips.RipsError, match="Invalid increment Y. Must be positive."):
|
|
surface_collection.new_regular_surface(increment_y=-1.0)
|
|
|
|
with pytest.raises(rips.RipsError, match="Invalid rotation."):
|
|
surface_collection.new_regular_surface(rotation=-1.0)
|
|
|
|
|
|
def test_surface_name_uniqueness(rips_instance, initialize_test):
|
|
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID"
|
|
rips_instance.project.load_case(path=case_path)
|
|
|
|
surface_collection = rips_instance.project.descendants(rips.SurfaceCollection)[0]
|
|
|
|
surface_collection.new_regular_surface(name="Top")
|
|
|
|
# The default policy is to fail on a name already used in the same folder
|
|
with pytest.raises(rips.RipsError, match="already exists"):
|
|
surface_collection.new_regular_surface(name="Top")
|
|
|
|
renamed = surface_collection.new_regular_surface(
|
|
name="Top", on_name_conflict=rips.NameConflictPolicy.AUTO_RENAME
|
|
)
|
|
assert renamed.surface_user_description == "Top_1"
|
|
|
|
# Names are case sensitive, so this is not a conflict
|
|
other_case = surface_collection.new_regular_surface(name="top")
|
|
assert other_case.surface_user_description == "top"
|
|
|
|
overwritten = surface_collection.new_regular_surface(
|
|
name="Top", on_name_conflict=rips.NameConflictPolicy.OVERWRITE
|
|
)
|
|
assert overwritten.surface_user_description == "Top"
|
|
|
|
names = [s.surface_user_description for s in surface_collection.surfaces_field()]
|
|
assert names.count("Top") == 1
|
|
|
|
# A different folder is a separate namespace
|
|
folder = surface_collection.add_folder(folder_name="Folder A")
|
|
in_folder = folder.new_regular_surface(name="Top")
|
|
assert in_folder.surface_user_description == "Top"
|
|
|
|
|
|
def test_import_surface_errors(rips_instance, initialize_test):
|
|
case_path = dataroot.PATH + "/Case_with_10_timesteps/Real0/BRUGGE_0000.EGRID"
|
|
case = rips_instance.project.load_case(path=case_path)
|
|
|
|
surface_collection = rips_instance.project.descendants(rips.SurfaceCollection)[0]
|
|
|
|
with pytest.raises(rips.RipsError, match="File name is empty"):
|
|
surface_collection.import_surface(file_name="")
|
|
|
|
with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
|
|
missing_path = Path(tmpdirname, "missing.irap").as_posix()
|
|
with pytest.raises(rips.RipsError, match="missing.irap"):
|
|
surface_collection.import_surface(file_name=missing_path)
|
|
|
|
corrupt_path = Path(tmpdirname, "corrupt.irap")
|
|
corrupt_path.write_text("this is not a surface file")
|
|
with pytest.raises(
|
|
rips.RipsError, match="Could not import surface from file .*corrupt.irap"
|
|
):
|
|
surface_collection.import_surface(file_name=corrupt_path.as_posix())
|
|
|
|
surface_path = Path(tmpdirname, "mysurface.ts")
|
|
surface_collection.new_surface(case, 5).export_to_file(surface_path.as_posix())
|
|
valid_content = surface_path.read_bytes()
|
|
imported = surface_collection.import_surface(file_name=surface_path.as_posix())
|
|
assert imported.surface_user_description == "mysurface.ts"
|
|
|
|
def surface_names():
|
|
return [
|
|
s.surface_user_description for s in surface_collection.surfaces_field()
|
|
]
|
|
|
|
# A failed overwrite must keep the existing surface
|
|
surface_path.unlink()
|
|
with pytest.raises(rips.RipsError, match="mysurface.ts"):
|
|
surface_collection.import_surface(
|
|
file_name=surface_path.as_posix(),
|
|
on_name_conflict=rips.NameConflictPolicy.OVERWRITE,
|
|
)
|
|
assert surface_names().count("mysurface.ts") == 1
|
|
|
|
surface_path.write_text("this is not a surface file")
|
|
with pytest.raises(rips.RipsError, match="mysurface.ts"):
|
|
surface_collection.import_surface(
|
|
file_name=surface_path.as_posix(),
|
|
on_name_conflict=rips.NameConflictPolicy.OVERWRITE,
|
|
)
|
|
assert surface_names().count("mysurface.ts") == 1
|
|
|
|
# A successful overwrite replaces the surface and keeps the name
|
|
surface_path.write_bytes(valid_content)
|
|
overwritten = surface_collection.import_surface(
|
|
file_name=surface_path.as_posix(),
|
|
on_name_conflict=rips.NameConflictPolicy.OVERWRITE,
|
|
)
|
|
assert overwritten.surface_user_description == "mysurface.ts"
|
|
assert surface_names().count("mysurface.ts") == 1
|
|
|
|
renamed = surface_collection.import_surface(
|
|
file_name=surface_path.as_posix(),
|
|
on_name_conflict=rips.NameConflictPolicy.AUTO_RENAME,
|
|
)
|
|
assert renamed.surface_user_description == "mysurface.ts_1"
|