14
14
from fastapi import APIRouter , Depends , Request , Body
15
15
16
16
from src .backend .auth .auth_helper import AuthenticatedUser , AuthHelper
17
-
18
- from src .services .sumo_access .surface_access import SurfaceAccess
19
17
import asyncio
20
18
from src .backend .primary .routers .surface import schemas
21
- from .test_async import async_get_cached_surf
22
- from .test_go import go_get_surface_blobs
19
+
23
20
from sumo .wrapper import SumoClient
24
- from fmu .sumo .explorer .objects import CaseCollection , Case , SurfaceCollection
21
+ from fmu .sumo .explorer .objects import CaseCollection
25
22
from src .services .utils .perf_timer import PerfTimer
26
- import base64
23
+
27
24
from io import BytesIO
28
- from azure .storage .blob .aio import BlobServiceClient , BlobClient , ContainerClient
25
+ from azure .storage .blob .aio import BlobClient , ContainerClient
29
26
import requests
30
27
31
28
LOGGER = logging .getLogger (__name__ )
@@ -42,169 +39,73 @@ async def well_intersection_reals_from_user_session(
42
39
) -> List [schemas .SurfaceIntersectionPoints ]:
43
40
body = await request .json ()
44
41
ensemble_ident = schemas .EnsembleIdent (** body .get ("ensemble_ident" ))
45
- realization_surface_set_spec = schemas .RealizationsSurfaceSetSpec (** body .get ("realizations_surface_set_spec" ))
42
+ realization_surface_set_spec = schemas .RealizationsSurfaceSetSpec (
43
+ ** body .get ("realizations_surface_set_spec" )
44
+ )
46
45
surface_fence_spec = schemas .SurfaceFenceSpec (** body .get ("surface_fence_spec" ))
47
46
timer = PerfTimer ()
48
47
# Config
49
48
case_uuid = ensemble_ident .case_uuid
50
- snames = realization_surface_set_spec .surface_names
51
- sattr = realization_surface_set_spec .surface_attribute
52
49
ensemble_name = ensemble_ident .ensemble_name
53
- realization_nums = realization_surface_set_spec .realization_nums
54
50
intersections = []
55
51
56
- uuids = get_uuids (
57
- case_uuid , ensemble_name , realization_nums , snames , sattr , authenticated_user .get_sumo_access_token ()
52
+ uuids = get_surface_set_uuids (
53
+ case_uuid ,
54
+ ensemble_name ,
55
+ realization_surface_set_spec ,
56
+ authenticated_user .get_sumo_access_token (),
58
57
)
59
58
base_uri , auth_token = get_base_uri_and_auth_token_for_case (
60
59
case_uuid , "prod" , authenticated_user .get_sumo_access_token ()
61
60
)
62
61
63
- async with ContainerClient .from_container_url (container_url = base_uri , credential = auth_token ) as container_client :
62
+ async with ContainerClient .from_container_url (
63
+ container_url = base_uri , credential = auth_token
64
+ ) as container_client :
64
65
coro_array = []
65
66
timer = PerfTimer ()
66
67
67
68
for uuid in uuids :
68
- coro_array .append (my_download_to_file (container_client = container_client , sumo_surf_uuid = uuid ))
69
+ coro_array .append (
70
+ download_blob (container_client = container_client , sumo_surf_uuid = uuid )
71
+ )
69
72
res_array = await asyncio .gather (* coro_array )
70
- dl_time_s = timer .lap_s ()
71
- print (f"download surfs: { dl_time_s :.2f} s" , flush = True )
72
- LOGGER .info (f"download surfs: { dl_time_s :.2f} s" , extra = {"download_surfs" : dl_time_s })
73
+ elapsed_download = timer .lap_s ()
73
74
74
75
tot_mb = 0
75
76
for res in res_array :
76
77
tot_mb += len (res ) / (1024 * 1024 )
77
- print (f"Total MB downloaded: { tot_mb :.2f} MB => { tot_mb / dl_time_s :.2f} MB/s" , flush = True )
78
- LOGGER .info (
79
- f"Total MB downloaded: { tot_mb :.2f} MB => { tot_mb / dl_time_s :.2f} MB/s" ,
80
- extra = {"total_mb" : tot_mb , "mb_per_s" : tot_mb / dl_time_s },
81
- )
82
78
83
- # surfs = [xtgeo.surface_from_file(BytesIO(bytestr), fformat="irap_binary") for bytestr in res_array]
84
79
surfaces = await load_xtgeo (res_array )
85
- print (f"convert surfs: { timer .lap_s ():.2f} s" , flush = True )
86
- fence_arr = np .array (
87
- [
88
- surface_fence_spec .x_points ,
89
- surface_fence_spec .y_points ,
90
- np .zeros (len (surface_fence_spec .y_points )),
91
- surface_fence_spec .cum_length ,
92
- ]
93
- ).T
94
- intersections = await make_intersections (surfaces , fence_arr )
95
-
96
- print (f"intersect surfs: { timer .lap_s ():.2f} s" , flush = True )
97
- return ORJSONResponse ([section .dict () for section in intersections ])
98
-
80
+ elapsed_xtgeo = timer .lap_s ()
99
81
100
- async def my_download_to_file (container_client : ContainerClient , sumo_surf_uuid ):
101
- blob_client : BlobClient = container_client .get_blob_client (blob = sumo_surf_uuid )
102
- download_stream = await blob_client .download_blob (
103
- max_concurrency = 4 ,
104
- )
105
- return await download_stream .readall ()
106
-
107
-
108
- @router .post ("/well_intersection_reals_from_user_session" )
109
- async def well_intersection_reals_from_user_session2 (
110
- request : Request ,
111
- authenticated_user : AuthenticatedUser = Depends (AuthHelper .get_authenticated_user ),
112
- ) -> List [schemas .SurfaceIntersectionPoints ]:
113
- body = await request .json ()
114
-
115
- ensemble_ident = schemas .EnsembleIdent (** body .get ("ensemble_ident" ))
116
- realization_surface_set_spec = schemas .RealizationsSurfaceSetSpec (** body .get ("realizations_surface_set_spec" ))
117
- surface_fence_spec = schemas .SurfaceFenceSpec (** body .get ("surface_fence_spec" ))
118
- timer = PerfTimer ()
119
- # Config
120
- case_uuid = ensemble_ident .case_uuid
121
- snames = realization_surface_set_spec .surface_names
122
- sattr = realization_surface_set_spec .surface_attribute
123
- ensemble_name = ensemble_ident .ensemble_name
124
- realization_nums = realization_surface_set_spec .realization_nums
125
- # Get uuids
126
- uuids = get_uuids (
127
- case_uuid , ensemble_name , realization_nums , snames , sattr , authenticated_user .get_sumo_access_token ()
128
- )
129
- elapsed_meta = timer .lap_ms ()
130
-
131
- # Check if cached
132
- uuids_to_download = []
133
- surfaces = []
134
- for uuid in uuids :
135
- possible_surface = await cache .get (f"{ authenticated_user ._user_id } -{ uuid } " )
136
- if possible_surface is None :
137
- uuids_to_download .append (uuid )
138
- else :
139
- surfaces .append (possible_surface )
140
- elapsed_cache = timer .lap_ms ()
141
- if uuids_to_download :
142
- # Download remaining
143
- data_map_b64 = go_get_surface_blobs (authenticated_user .get_sumo_access_token (), case_uuid , uuids_to_download )
144
- elapsed_download = timer .lap_ms ()
145
-
146
- # Convert to xtgeo
147
- downloaded_surface_dict = await b64_to_xtgeo (data_map_b64 )
148
- elapsed_xtgeo = timer .lap_ms ()
149
-
150
- # Add to cache
151
- for uuid , surface in downloaded_surface_dict .items ():
152
- await cache .set (f"{ authenticated_user ._user_id } -{ uuid } " , surface )
153
- surfaces .append (surface )
154
- else :
155
- elapsed_download = 0
156
- elapsed_xtgeo = 0
157
- # Intersect
158
- fence_arr = np .array (
159
- [
160
- surface_fence_spec .x_points ,
161
- surface_fence_spec .y_points ,
162
- np .zeros (len (surface_fence_spec .y_points )),
163
- surface_fence_spec .cum_length ,
164
- ]
165
- ).T
166
- intersections = await make_intersections (surfaces , fence_arr )
167
- elapsed_intersect = timer .lap_ms ()
82
+ intersections = await make_intersections (surfaces , surface_fence_spec )
83
+ elapsed_intersect = timer .lap_s ()
168
84
169
- result = [intersection .dict () for intersection in intersections ]
170
- elapsed_response_format = timer .lap_ms ()
171
85
LOGGER .info (
172
86
f"Got intersected surface set from Sumo: { timer .elapsed_ms ()} ms ("
173
- f"meta={ elapsed_meta } ms, "
174
- f"cache={ elapsed_cache } ms, "
175
87
f"download={ elapsed_download } ms, "
176
88
f"xtgeo={ elapsed_xtgeo } ms, "
177
89
f"intersect={ elapsed_intersect } ms, "
178
- f"response_format={ elapsed_response_format } ms) " ,
90
+ f"size={ tot_mb :.2f} MB, "
91
+ f"speed={ tot_mb / elapsed_download :.2f} MB/s)" ,
179
92
extra = {
180
- "meta" : elapsed_meta ,
181
- "cache" : elapsed_cache ,
182
93
"download" : elapsed_download ,
183
94
"xtgeo" : elapsed_xtgeo ,
184
95
"intersect" : elapsed_intersect ,
185
- "response_format" : elapsed_response_format ,
96
+ "size" : tot_mb ,
97
+ "speed" : tot_mb / elapsed_download ,
186
98
},
187
99
)
188
- return ORJSONResponse (result )
189
-
100
+ return ORJSONResponse ([section .dict () for section in intersections ])
190
101
191
- async def b64_to_xtgeo (data_map_b64 ):
192
- def to_xtgeo (object_id , b64_blob ):
193
- bytestr = base64 .b64decode (b64_blob )
194
- xtgeo_surface = xtgeo .surface_from_file (BytesIO (bytestr ), fformat = "irap_binary" )
195
- return {object_id : xtgeo_surface }
196
102
197
- loop = asyncio .get_running_loop ()
198
- with ThreadPoolExecutor () as executor :
199
- tasks = [
200
- loop .run_in_executor (executor , to_xtgeo , object_id , b64_blob )
201
- for object_id , b64_blob in data_map_b64 .items ()
202
- ]
203
- results = await asyncio .gather (* tasks )
204
- downloaded_surface_dict = {}
205
- for result in results :
206
- downloaded_surface_dict .update (result )
207
- return downloaded_surface_dict
103
+ async def download_blob (container_client : ContainerClient , sumo_surf_uuid ):
104
+ blob_client : BlobClient = container_client .get_blob_client (blob = sumo_surf_uuid )
105
+ download_stream = await blob_client .download_blob (
106
+ max_concurrency = 4 ,
107
+ )
108
+ return await download_stream .readall ()
208
109
209
110
210
111
def make_intersection (surf , fence_arr ):
@@ -217,11 +118,21 @@ def make_intersection(surf, fence_arr):
217
118
return intersection
218
119
219
120
220
- async def make_intersections (surfaces , fence_arr ):
121
+ async def make_intersections (surfaces , surface_fence_spec ):
221
122
loop = asyncio .get_running_loop ()
222
-
123
+ fence_arr = np .array (
124
+ [
125
+ surface_fence_spec .x_points ,
126
+ surface_fence_spec .y_points ,
127
+ np .zeros (len (surface_fence_spec .y_points )),
128
+ surface_fence_spec .cum_length ,
129
+ ]
130
+ ).T
223
131
with ProcessPoolExecutor () as executor :
224
- tasks = [loop .run_in_executor (executor , make_intersection , surf , fence_arr ) for surf in surfaces ]
132
+ tasks = [
133
+ loop .run_in_executor (executor , make_intersection , surf , fence_arr )
134
+ for surf in surfaces
135
+ ]
225
136
intersections = await asyncio .gather (* tasks )
226
137
return intersections
227
138
@@ -233,20 +144,27 @@ def load_surf(bytestr) -> xtgeo.RegularSurface:
233
144
async def load_xtgeo (res_array ):
234
145
loop = asyncio .get_running_loop ()
235
146
with ProcessPoolExecutor () as executor :
236
- tasks = [loop .run_in_executor (executor , load_surf , bytestr ) for bytestr in res_array ]
147
+ tasks = [
148
+ loop .run_in_executor (executor , load_surf , bytestr ) for bytestr in res_array
149
+ ]
237
150
surfaces = await asyncio .gather (* tasks )
238
151
return surfaces
239
152
240
153
241
- def get_uuids (case_uuid , ensemble_name , realization_nums , snames , sattr , bearer_token ):
154
+ def get_surface_set_uuids (
155
+ case_uuid ,
156
+ ensemble_name ,
157
+ realization_surface_set_spec : schemas .RealizationsSurfaceSetSpec ,
158
+ bearer_token ,
159
+ ):
242
160
sumo_client = SumoClient (env = "prod" , token = bearer_token , interactive = False )
243
161
case_collection = CaseCollection (sumo_client ).filter (uuid = case_uuid )
244
162
case = case_collection [0 ]
245
163
surface_collection = case .surfaces .filter (
246
164
iteration = ensemble_name ,
247
- name = snames ,
248
- tagname = sattr ,
249
- realization = realization_nums ,
165
+ name = realization_surface_set_spec . surface_names ,
166
+ tagname = realization_surface_set_spec . surface_attribute ,
167
+ realization = realization_surface_set_spec . realization_nums ,
250
168
)
251
169
return [surf .uuid for surf in surface_collection ]
252
170
0 commit comments