Skip to content

Commit cf522d0

Browse files
Various fixes to backend. Fetch multiple stat surfaces at the same time
1 parent 41c950f commit cf522d0

File tree

3 files changed

+70
-58
lines changed

3 files changed

+70
-58
lines changed

backend/src/backend/primary/routers/surface/router.py

+17-24
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ async def get_property_surface_resampled_to_statistical_static_surface(
195195
name=name_mesh,
196196
attribute=attribute_mesh,
197197
)
198-
xtgeo_surf_property = await access.get_statistical_surface_data_async(
198+
xtgeo_surf_property = await access.get_statistical_surfaces_data_async(
199199
statistic_function=service_stat_func_to_compute,
200200
name=name_property,
201201
attribute=attribute_property,
@@ -237,41 +237,35 @@ async def well_intersection_statistics(
237237
access = await SurfaceAccess.from_case_uuid(
238238
authenticated_user.get_sumo_access_token(), ensemble_ident.case_uuid, ensemble_ident.ensemble_name
239239
)
240-
surfaces = []
241240

242-
async def fetch_surface(statistic, surface_name):
243-
surface = await access.get_statistical_surface_data_async(
244-
statistic_function=StatisticFunction.from_string_value(statistic),
241+
async def fetch_surface(statistics, surface_name):
242+
surfaces = await access.get_statistical_surfaces_data_async(
243+
statistic_functions=[StatisticFunction.from_string_value(statistic) for statistic in statistics],
245244
name=surface_name,
246245
attribute=statistical_surface_set_spec.surface_attribute,
247246
realizations=statistical_surface_set_spec.realization_nums,
248247
)
249-
surface.name = surface_name + "_" + statistic
250-
return surface
248+
print(surfaces, "fetch")
249+
return surfaces
251250

252251
async def fetch_all_surfaces():
253252
tasks = []
254-
for statistic in statistical_surface_set_spec.statistic_function:
255-
for surface_name in statistical_surface_set_spec.surface_names:
256-
# Create a task for each combination of statistic and surface_name
257-
task = fetch_surface(statistic, surface_name)
258-
tasks.append(task)
253+
for surface_name in statistical_surface_set_spec.surface_names:
254+
task = fetch_surface(statistical_surface_set_spec.statistic_function, surface_name)
255+
tasks.append(task)
259256

260257
# Run all the tasks concurrently
261258
tmp_surfaces = await asyncio.gather(*tasks)
259+
print(tmp_surfaces)
262260
return tmp_surfaces
263261

264-
# for statistic in statistical_surface_set_spec.statistic_function:
265-
# for surface_name in statistical_surface_set_spec.surface_names:
266-
# surface = await access.get_statistical_surface_data_async(
267-
# statistic_function=StatisticFunction.from_string_value(statistic),
268-
# name=surface_name,
269-
# attribute=statistical_surface_set_spec.surface_attribute,
270-
# realizations=statistical_surface_set_spec.realization_nums,
271-
# )
272-
# surface.name = surface_name + "_" + statistic
273-
# surfaces.append(surface)
274-
surfaces = await fetch_all_surfaces()
262+
nested_surfaces = await fetch_all_surfaces()
263+
surfaces = []
264+
if nested_surfaces:
265+
for surface_list in nested_surfaces:
266+
if surface_list:
267+
for surface in surface_list:
268+
surfaces.append(surface)
275269

276270
fence_arr = np.array(
277271
[
@@ -282,7 +276,6 @@ async def fetch_all_surfaces():
282276
]
283277
).T
284278
intersections = await make_intersections(surfaces, fence_arr)
285-
print(intersections)
286279
return intersections
287280

288281

backend/src/backend/primary/routers/well/router.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22
from typing import List, Union
33

4-
from fastapi import APIRouter, Depends, Query
4+
from fastapi import APIRouter, Depends, Query, HTTPException
55

66
from src.services.smda_access import mocked_drogon_smda_access
77
from src.services.smda_access.well_access import WellAccess
@@ -24,11 +24,9 @@ async def get_well_headers(
2424
# fmt:on
2525
) -> List[WellBoreHeader]:
2626
"""Get well headers for all wells in the field"""
27-
print(case_uuid, " case_uuid FIELD")
2827
case_inspector = await SumoCase.from_case_uuid(authenticated_user.get_sumo_access_token(), case_uuid)
2928
field_identifier = (await case_inspector.get_field_identifiers())[0]
3029
well_access: Union[WellAccess, mocked_drogon_smda_access.WellAccess]
31-
print(field_identifier, "FIELD IDENTIFIER FIELD")
3230
if field_identifier == "DROGON":
3331
# Handle DROGON
3432
well_access = mocked_drogon_smda_access.WellAccess(authenticated_user.get_smda_access_token())
@@ -50,7 +48,6 @@ async def get_field_well_trajectories(
5048
case_inspector = await SumoCase.from_case_uuid(authenticated_user.get_sumo_access_token(), case_uuid)
5149
field_identifier = (await case_inspector.get_field_identifiers())[0]
5250
well_access: Union[WellAccess, mocked_drogon_smda_access.WellAccess]
53-
print(field_identifier, "FIELD IDENTIFIER FIELD")
5451
if field_identifier == "DROGON":
5552
# Handle DROGON
5653
well_access = mocked_drogon_smda_access.WellAccess(authenticated_user.get_smda_access_token())
@@ -78,4 +75,8 @@ async def get_well_trajectories(
7875
else:
7976
well_access = WellAccess(authenticated_user.get_smda_access_token())
8077

81-
return await well_access.get_wellbore_trajectories(wellbore_uuids=wellbore_uuids)
78+
try:
79+
trajectories = await well_access.get_wellbore_trajectories(wellbore_uuids=wellbore_uuids)
80+
return trajectories
81+
except KeyError:
82+
raise HTTPException(status_code=404, detail="No wellbore trajectory data found")

backend/src/services/sumo_access/surface_access.py

+47-29
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,14 @@ async def get_realization_surface_data_async(
138138

139139
return xtgeo_surf
140140

141-
async def get_statistical_surface_data_async(
141+
async def get_statistical_surfaces_data_async(
142142
self,
143-
statistic_function: StatisticFunction,
143+
statistic_functions: list[StatisticFunction],
144144
name: str,
145145
attribute: str,
146146
time_or_interval_str: Optional[str] = None,
147147
realizations: Optional[List[int]] = None,
148-
) -> Optional[xtgeo.RegularSurface]:
148+
) -> list[xtgeo.RegularSurface]:
149149
"""
150150
Compute statistic and return surface data
151151
"""
@@ -192,12 +192,12 @@ async def get_statistical_surface_data_async(
192192

193193
et_collect_reals_ms = timer.lap_ms()
194194

195-
xtgeo_surf = await _compute_statistical_surface_async(statistic_function, surface_collection)
195+
xtgeo_surfs = await _compute_statistical_surfaces_async(statistic_functions, surface_collection)
196+
print(xtgeo_surfs)
196197
et_calc_stat_ms = timer.lap_ms()
197198

198-
if not xtgeo_surf:
199+
if not xtgeo_surfs:
199200
LOGGER.warning(f"Could not calculate statistical surface using Sumo for {addr_str}")
200-
return None
201201

202202
LOGGER.debug(
203203
f"Calculated statistical surface using Sumo in: {timer.elapsed_ms()}ms ("
@@ -207,32 +207,50 @@ async def get_statistical_surface_data_async(
207207
f"({addr_str} {len(realizations)=} )"
208208
)
209209

210-
return xtgeo_surf
210+
return xtgeo_surfs
211211

212212
def _make_addr_str(self, real_num: int, name: str, attribute: str, date_str: Optional[str]) -> str:
213213
addr_str = f"R:{real_num}__N:{name}__A:{attribute}__D:{date_str}__I:{self._iteration_name}__C:{self._case_uuid}"
214214
return addr_str
215215

216216

217-
async def _compute_statistical_surface_async(
218-
statistic: StatisticFunction, surface_coll: SurfaceCollection
219-
) -> xtgeo.RegularSurface:
220-
xtgeo_surf: xtgeo.RegularSurface = None
221-
if statistic == StatisticFunction.MIN:
222-
xtgeo_surf = await surface_coll.min_async()
223-
elif statistic == StatisticFunction.MAX:
224-
xtgeo_surf = await surface_coll.max_async()
225-
elif statistic == StatisticFunction.MEAN:
226-
xtgeo_surf = await surface_coll.mean_async()
227-
elif statistic == StatisticFunction.P10:
228-
xtgeo_surf = await surface_coll.p10_async()
229-
elif statistic == StatisticFunction.P90:
230-
xtgeo_surf = await surface_coll.p90_async()
231-
elif statistic == StatisticFunction.P50:
232-
xtgeo_surf = await surface_coll.p50_async()
233-
elif statistic == StatisticFunction.STD:
234-
xtgeo_surf = await surface_coll.std_async()
235-
else:
236-
raise ValueError("Unhandled statistic function")
237-
238-
return xtgeo_surf
217+
async def _compute_statistical_surfaces_async(
218+
statistics: StatisticFunction, surface_coll: SurfaceCollection
219+
) -> list[xtgeo.RegularSurface]:
220+
# xtgeo_surf: xtgeo.RegularSurface = None
221+
# if statistic == StatisticFunction.MIN:
222+
# xtgeo_surf = await surface_coll.min_async()
223+
# elif statistic == StatisticFunction.MAX:
224+
# xtgeo_surf = await surface_coll.max_async()
225+
# elif statistic == StatisticFunction.MEAN:
226+
# xtgeo_surf = await surface_coll.mean_async()
227+
# elif statistic == StatisticFunction.P10:
228+
# xtgeo_surf = await surface_coll.p10_async()
229+
# elif statistic == StatisticFunction.P90:
230+
# xtgeo_surf = await surface_coll.p90_async()
231+
# elif statistic == StatisticFunction.P50:
232+
# xtgeo_surf = await surface_coll.p50_async()
233+
# elif statistic == StatisticFunction.STD:
234+
# xtgeo_surf = await surface_coll.std_async()
235+
# else:
236+
# raise ValueError("Unhandled statistic function")
237+
238+
# return xtgeo_surf
239+
objects = await surface_coll._utils.get_objects_async(500, surface_coll._query, ["_id"])
240+
object_ids = list(map(lambda obj: obj["_id"], objects))
241+
res = await surface_coll._sumo.post_async(
242+
"/surface/aggregate",
243+
json={"operation": [stat.value for stat in statistics], "object_ids": object_ids},
244+
)
245+
res_bytes = res.content
246+
# print(res.content)
247+
import zipfile
248+
249+
surfs = []
250+
with zipfile.ZipFile(BytesIO(res_bytes)) as z:
251+
# return z.read(z.namelist()[0])
252+
for stat_op in z.namelist():
253+
xtgeo_surf = xtgeo.surface_from_file(BytesIO(z.read(stat_op)))
254+
xtgeo_surf.name = StatisticFunction.from_string_value(stat_op.upper())
255+
surfs.append(xtgeo_surf)
256+
return surfs

0 commit comments

Comments
 (0)