Skip to content

Commit 20542c9

Browse files
Adjustments to backend (and related required changes to frontend) in preparation of 2D viewer (equinor#808)
Co-authored-by: Hans Kallekleiv <[email protected]>
1 parent a028574 commit 20542c9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1122
-881
lines changed

backend_py/primary/primary/routers/explore.py

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class EnsembleInfo(BaseModel):
3030
class EnsembleDetails(BaseModel):
3131
name: str
3232
field_identifier: str
33+
stratigraphic_column_identifier: str
3334
case_name: str
3435
case_uuid: str
3536
realizations: Sequence[int]
@@ -91,6 +92,7 @@ async def get_ensemble_details(
9192
case_name = await case_inspector.get_case_name_async()
9293
realizations = await case_inspector.get_realizations_in_iteration_async(ensemble_name)
9394
field_identifiers = await case_inspector.get_field_identifiers_async()
95+
stratigraphic_column_identifier = await case_inspector.get_stratigraphic_column_identifier_async()
9496

9597
if len(field_identifiers) != 1:
9698
raise NotImplementedError("Multiple field identifiers not supported")
@@ -101,4 +103,5 @@ async def get_ensemble_details(
101103
case_uuid=case_uuid,
102104
realizations=realizations,
103105
field_identifier=field_identifiers[0],
106+
stratigraphic_column_identifier=stratigraphic_column_identifier,
104107
)

backend_py/primary/primary/routers/polygons/router.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from webviz_pkg.core_utils.perf_timer import PerfTimer
66

77
from primary.auth.auth_helper import AuthHelper
8-
from primary.services.smda_access.mocked_drogon_smda_access import _mocked_stratigraphy_access
9-
from primary.services.smda_access.stratigraphy_access import StratigraphyAccess
8+
from primary.services.smda_access.drogon import DrogonSmdaAccess
9+
from primary.services.smda_access import SmdaAccess
1010
from primary.services.smda_access.stratigraphy_utils import sort_stratigraphic_names_by_hierarchy
1111
from primary.services.sumo_access.case_inspector import CaseInspector
1212
from primary.services.sumo_access.polygons_access import PolygonsAccess
@@ -34,14 +34,15 @@ async def get_polygons_directory(
3434
polygons_dir = await access.get_polygons_directory_async()
3535

3636
case_inspector = CaseInspector.from_case_uuid(authenticated_user.get_sumo_access_token(), case_uuid)
37+
field_identifiers = await case_inspector.get_field_identifiers_async()
3738
strat_column_identifier = await case_inspector.get_stratigraphic_column_identifier_async()
38-
strat_access: Union[StratigraphyAccess, _mocked_stratigraphy_access.StratigraphyAccess]
39+
smda_access: Union[SmdaAccess, DrogonSmdaAccess]
3940

4041
if strat_column_identifier == "DROGON_HAS_NO_STRATCOLUMN":
41-
strat_access = _mocked_stratigraphy_access.StratigraphyAccess(authenticated_user.get_smda_access_token())
42+
smda_access = DrogonSmdaAccess()
4243
else:
43-
strat_access = StratigraphyAccess(authenticated_user.get_smda_access_token())
44-
strat_units = await strat_access.get_stratigraphic_units(strat_column_identifier)
44+
smda_access = SmdaAccess(authenticated_user.get_smda_access_token(), field_identifier=field_identifiers[0])
45+
strat_units = await smda_access.get_stratigraphic_units(strat_column_identifier)
4546
sorted_stratigraphic_surfaces = sort_stratigraphic_names_by_hierarchy(strat_units)
4647

4748
return converters.to_api_polygons_directory(polygons_dir, sorted_stratigraphic_surfaces)

backend_py/primary/primary/routers/polygons/schemas.py

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class PolygonsAttributeType(str, Enum):
2020
PINCHOUT = "pinchout" # Values are pinchouts
2121
SUBCROP = "subcrop" # Values are subcrops
2222
FAULT_LINES = "fault_lines" # Values are fault lines
23+
NAMED_AREA = "named_area" # Values are named areas, e.g. CCS containment polygons
2324

2425

2526
class PolygonsMeta(BaseModel):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from typing import List
2+
3+
import orjson
4+
import numpy as np
5+
import xtgeo
6+
7+
from . import schemas
8+
9+
10+
def surface_to_float32_array(values: np.ndarray) -> List[float]:
11+
values = values.astype(np.float32)
12+
np.ma.set_fill_value(values, np.nan)
13+
values = np.ma.filled(values)
14+
15+
# Rotate 90 deg left.
16+
# This will cause the width of to run along the X axis
17+
# and height of along Y axis (starting from bottom.)
18+
values = np.rot90(values)
19+
20+
return values.flatten().tolist()
21+
22+
23+
def to_api_surface_data(
24+
xtgeo_surf: xtgeo.RegularSurface, property_values: np.ndarray
25+
) -> schemas.SurfaceMeshAndProperty:
26+
"""
27+
Create API SurfaceData from xtgeo regular surface
28+
"""
29+
float32_mesh = surface_to_float32_array(xtgeo_surf.values)
30+
float32_property = surface_to_float32_array(property_values)
31+
32+
return schemas.SurfaceMeshAndProperty(
33+
x_ori=xtgeo_surf.xori,
34+
y_ori=xtgeo_surf.yori,
35+
x_count=xtgeo_surf.ncol,
36+
y_count=xtgeo_surf.nrow,
37+
x_inc=xtgeo_surf.xinc,
38+
y_inc=xtgeo_surf.yinc,
39+
x_min=xtgeo_surf.xmin,
40+
x_max=xtgeo_surf.xmax,
41+
y_min=xtgeo_surf.ymin,
42+
y_max=xtgeo_surf.ymax,
43+
mesh_value_min=xtgeo_surf.values.min(),
44+
mesh_value_max=xtgeo_surf.values.max(),
45+
property_value_min=property_values.min(),
46+
property_value_max=property_values.max(),
47+
rot_deg=xtgeo_surf.rotation,
48+
mesh_data=orjson.dumps(float32_mesh).decode("utf-8"), # pylint: disable=maybe-no-member
49+
property_data=orjson.dumps(float32_property).decode("utf-8"), # pylint: disable=maybe-no-member
50+
)

backend_py/primary/primary/routers/seismic/schemas.py

+20
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,23 @@ class SeismicFenceData(BaseModel):
5858
num_samples_per_trace: int
5959
min_fence_depth: float
6060
max_fence_depth: float
61+
62+
63+
class SurfaceMeshAndProperty(BaseModel):
64+
x_ori: float
65+
y_ori: float
66+
x_count: int
67+
y_count: int
68+
x_inc: float
69+
y_inc: float
70+
x_min: float
71+
x_max: float
72+
y_min: float
73+
y_max: float
74+
mesh_value_min: float
75+
mesh_value_max: float
76+
property_value_min: float
77+
property_value_max: float
78+
rot_deg: float
79+
mesh_data: str
80+
property_data: str

backend_py/primary/primary/routers/surface/converters.py

+20
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from primary.services.utils.surface_intersect_with_polyline import XtgeoSurfaceIntersectionResult
1212
from primary.services.utils.surface_to_float32 import surface_to_float32_numpy_array
1313
from primary.services.utils.surface_to_png import surface_to_png_bytes_optimized
14+
from primary.services.smda_access import StratigraphicUnit
1415

1516
from . import schemas
1617

@@ -174,3 +175,22 @@ def to_api_surface_intersection(
174175
z_points=xtgeo_surface_intersection.zval,
175176
cum_lengths=xtgeo_surface_intersection.distance,
176177
)
178+
179+
180+
def to_api_stratigraphic_unit(
181+
stratigraphic_unit: StratigraphicUnit,
182+
) -> schemas.StratigraphicUnit:
183+
return schemas.StratigraphicUnit(
184+
identifier=stratigraphic_unit.identifier,
185+
top=stratigraphic_unit.top,
186+
base=stratigraphic_unit.base,
187+
stratUnitLevel=stratigraphic_unit.strat_unit_level,
188+
stratUnitType=stratigraphic_unit.strat_unit_type,
189+
topAge=stratigraphic_unit.top_age,
190+
baseAge=stratigraphic_unit.base_age,
191+
stratUnitParent=stratigraphic_unit.strat_unit_parent,
192+
colorR=stratigraphic_unit.color_r,
193+
colorG=stratigraphic_unit.color_g,
194+
colorB=stratigraphic_unit.color_b,
195+
lithologyType=stratigraphic_unit.lithology_type,
196+
)

backend_py/primary/primary/routers/surface/router.py

+25-6
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88
from primary.services.sumo_access.case_inspector import CaseInspector
99
from primary.services.sumo_access.surface_access import SurfaceAccess
10-
from primary.services.smda_access.stratigraphy_access import StratigraphyAccess, StratigraphicUnit
10+
from primary.services.smda_access import SmdaAccess, StratigraphicUnit
1111
from primary.services.smda_access.stratigraphy_utils import sort_stratigraphic_names_by_hierarchy
12-
from primary.services.smda_access.mocked_drogon_smda_access import _mocked_stratigraphy_access
12+
from primary.services.smda_access.drogon import DrogonSmdaAccess
1313
from primary.services.utils.statistic_function import StatisticFunction
1414
from primary.services.utils.surface_intersect_with_polyline import intersect_surface_with_polyline
1515
from primary.services.utils.authenticated_user import AuthenticatedUser
@@ -295,22 +295,41 @@ async def get_misfit_surface_data(
295295
raise HTTPException(status.HTTP_501_NOT_IMPLEMENTED)
296296

297297

298+
@router.get("/stratigraphic_units")
299+
async def get_stratigraphic_units(
300+
# fmt:off
301+
response: Response,
302+
authenticated_user: Annotated[AuthenticatedUser, Depends(AuthHelper.get_authenticated_user)],
303+
case_uuid: Annotated[str, Query(description="Sumo case uuid")],
304+
# fmt:on
305+
) -> list[schemas.StratigraphicUnit]:
306+
perf_metrics = ResponsePerfMetrics(response)
307+
308+
strat_units = await _get_stratigraphic_units_for_case_async(authenticated_user, case_uuid)
309+
api_strat_units = [converters.to_api_stratigraphic_unit(strat_unit) for strat_unit in strat_units]
310+
311+
LOGGER.info(f"Got stratigraphic units in: {perf_metrics.to_string()}")
312+
313+
return api_strat_units
314+
315+
298316
async def _get_stratigraphic_units_for_case_async(
299317
authenticated_user: AuthenticatedUser, case_uuid: str
300318
) -> list[StratigraphicUnit]:
301319
perf_metrics = PerfMetrics()
302320

303321
case_inspector = CaseInspector.from_case_uuid(authenticated_user.get_sumo_access_token(), case_uuid)
322+
field_identifiers = await case_inspector.get_field_identifiers_async()
304323
strat_column_identifier = await case_inspector.get_stratigraphic_column_identifier_async()
305324
perf_metrics.record_lap("get-strat-ident")
306325

307-
strat_access: StratigraphyAccess | _mocked_stratigraphy_access.StratigraphyAccess
326+
smda_access: SmdaAccess | DrogonSmdaAccess
308327
if strat_column_identifier == "DROGON_HAS_NO_STRATCOLUMN":
309-
strat_access = _mocked_stratigraphy_access.StratigraphyAccess(authenticated_user.get_smda_access_token())
328+
smda_access = DrogonSmdaAccess()
310329
else:
311-
strat_access = StratigraphyAccess(authenticated_user.get_smda_access_token())
330+
smda_access = SmdaAccess(authenticated_user.get_smda_access_token(), field_identifier=field_identifiers[0])
312331

313-
strat_units = await strat_access.get_stratigraphic_units(strat_column_identifier)
332+
strat_units = await smda_access.get_stratigraphic_units(strat_column_identifier)
314333
perf_metrics.record_lap("get-strat-units")
315334

316335
LOGGER.info(f"Got stratigraphic units for case in : {perf_metrics.to_string()}")

backend_py/primary/primary/routers/surface/schemas.py

+15
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,18 @@ class SurfaceRealizationSampleValues(BaseModel):
164164
class PointSetXY(BaseModel):
165165
x_points: list[float]
166166
y_points: list[float]
167+
168+
169+
class StratigraphicUnit(BaseModel):
170+
identifier: str
171+
top: str
172+
base: str
173+
stratUnitLevel: int
174+
stratUnitType: str
175+
topAge: int | float
176+
baseAge: int | float
177+
stratUnitParent: str | None
178+
colorR: int
179+
colorG: int
180+
colorB: int
181+
lithologyType: int | float | str = "unknown"

backend_py/primary/primary/routers/well/converters.py

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def convert_wellbore_pick_to_schema(wellbore_pick: WellborePick) -> schemas.Well
1919
md=wellbore_pick.md,
2020
mdMsl=wellbore_pick.md_msl,
2121
uniqueWellboreIdentifier=wellbore_pick.unique_wellbore_identifier,
22+
wellboreUuid=wellbore_pick.wellbore_uuid,
2223
pickIdentifier=wellbore_pick.pick_identifier,
2324
confidence=wellbore_pick.confidence,
2425
depthReferencePoint=wellbore_pick.depth_reference_point,
@@ -57,6 +58,8 @@ def convert_wellbore_header_to_schema(
5758
wellNorthing=drilled_wellbore_header.well_northing,
5859
depthReferencePoint=drilled_wellbore_header.depth_reference_point,
5960
depthReferenceElevation=drilled_wellbore_header.depth_reference_elevation,
61+
wellborePurpose=(drilled_wellbore_header.wellbore_purpose if drilled_wellbore_header.wellbore_purpose else ""),
62+
wellboreStatus=drilled_wellbore_header.wellbore_status if drilled_wellbore_header.wellbore_status else "",
6063
)
6164

6265

0 commit comments

Comments
 (0)