pyetp 0.0.32__tar.gz → 0.0.34__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyetp-0.0.32 → pyetp-0.0.34}/PKG-INFO +3 -4
- {pyetp-0.0.32 → pyetp-0.0.34}/pyetp/client.py +100 -144
- {pyetp-0.0.32 → pyetp-0.0.34}/pyetp/config.py +6 -11
- pyetp-0.0.34/pyetp/types.py +113 -0
- {pyetp-0.0.32 → pyetp-0.0.34}/pyetp/uri.py +3 -4
- pyetp-0.0.34/pyetp/utils.py +15 -0
- {pyetp-0.0.32 → pyetp-0.0.34}/pyetp/utils_xml.py +21 -19
- {pyetp-0.0.32 → pyetp-0.0.34}/pyproject.toml +3 -3
- pyetp-0.0.32/pyetp/types.py +0 -48
- pyetp-0.0.32/pyetp/utils.py +0 -6
- {pyetp-0.0.32 → pyetp-0.0.34}/LICENSE.md +0 -0
- {pyetp-0.0.32 → pyetp-0.0.34}/README.md +0 -0
- {pyetp-0.0.32 → pyetp-0.0.34}/pyetp/__init__.py +0 -0
- {pyetp-0.0.32 → pyetp-0.0.34}/pyetp/resqml_objects/__init__.py +0 -0
- {pyetp-0.0.32 → pyetp-0.0.34}/pyetp/resqml_objects/generated.py +0 -0
- {pyetp-0.0.32 → pyetp-0.0.34}/pyetp/utils_arrays.py +0 -0
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pyetp
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.34
|
|
4
4
|
Summary: Interface with OSDU RDDMS using ETP protocol
|
|
5
5
|
Author: Adam Cheng
|
|
6
6
|
Author-email: 52572642+adamchengtkc@users.noreply.github.com
|
|
7
|
-
Requires-Python: >=3.
|
|
7
|
+
Requires-Python: >=3.10,<3.13
|
|
8
8
|
Classifier: Development Status :: 3 - Alpha
|
|
9
9
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
14
|
Requires-Dist: async-lru (>=2.0.4,<3.0.0)
|
|
16
15
|
Requires-Dist: async-timeout (>=5.0,<6.0) ; python_version < "3.11"
|
|
17
|
-
Requires-Dist: etpproto (
|
|
16
|
+
Requires-Dist: etpproto (>=1.0.7,<2.0.0)
|
|
18
17
|
Requires-Dist: lxml (>=4.9.4,<6.0)
|
|
19
18
|
Requires-Dist: numpy (>=1.26.3,<2.0.0)
|
|
20
19
|
Requires-Dist: pyarrow (>=15.0.0,<16.0.0)
|
|
@@ -5,10 +5,8 @@ import sys
|
|
|
5
5
|
import typing as T
|
|
6
6
|
import uuid
|
|
7
7
|
from collections import defaultdict
|
|
8
|
-
from contextlib import asynccontextmanager
|
|
9
8
|
from types import TracebackType
|
|
10
9
|
import time
|
|
11
|
-
|
|
12
10
|
import numpy as np
|
|
13
11
|
import websockets
|
|
14
12
|
from etpproto.connection import (CommunicationProtocol, ConnectionType,
|
|
@@ -18,12 +16,16 @@ from pydantic import SecretStr
|
|
|
18
16
|
from scipy.interpolate import griddata
|
|
19
17
|
from xtgeo import RegularSurface
|
|
20
18
|
|
|
19
|
+
|
|
21
20
|
import pyetp.resqml_objects as ro
|
|
21
|
+
#import energyml.resqml.v2_0_1.resqmlv2 as ro
|
|
22
|
+
#import energyml.eml.v2_0.commonv2 as roc
|
|
22
23
|
from pyetp import utils_arrays, utils_xml
|
|
23
24
|
from pyetp.config import SETTINGS
|
|
24
25
|
from pyetp.types import *
|
|
25
26
|
from pyetp.uri import DataObjectURI, DataspaceURI
|
|
26
|
-
from pyetp.utils import short_id
|
|
27
|
+
from pyetp.utils import short_id, batched
|
|
28
|
+
#from asyncio import timeout
|
|
27
29
|
|
|
28
30
|
try:
|
|
29
31
|
# for py >3.11, we can raise grouped exceptions
|
|
@@ -36,7 +38,7 @@ try:
|
|
|
36
38
|
from asyncio import timeout
|
|
37
39
|
except ImportError:
|
|
38
40
|
import async_timeout
|
|
39
|
-
|
|
41
|
+
from contextlib import asynccontextmanager
|
|
40
42
|
@asynccontextmanager
|
|
41
43
|
async def timeout(delay: T.Optional[float]) -> T.Any:
|
|
42
44
|
try:
|
|
@@ -50,9 +52,6 @@ logger = logging.getLogger(__name__)
|
|
|
50
52
|
logger.setLevel(logging.INFO)
|
|
51
53
|
|
|
52
54
|
|
|
53
|
-
MAXPAYLOADSIZE = 10_000_000 # 10MB
|
|
54
|
-
|
|
55
|
-
|
|
56
55
|
class ETPError(Exception):
|
|
57
56
|
def __init__(self, message: str, code: int):
|
|
58
57
|
self.message = message
|
|
@@ -88,16 +87,16 @@ class ETPClient(ETPConnection):
|
|
|
88
87
|
_recv_events: T.Dict[int, asyncio.Event]
|
|
89
88
|
_recv_buffer: T.Dict[int, T.List[ETPModel]]
|
|
90
89
|
|
|
91
|
-
def __init__(self, ws: websockets.WebSocketClientProtocol,
|
|
90
|
+
def __init__(self, ws: websockets.WebSocketClientProtocol, timeout=10.):
|
|
92
91
|
super().__init__(connection_type=ConnectionType.CLIENT)
|
|
93
92
|
self._recv_events = {}
|
|
94
93
|
self._recv_buffer = defaultdict(lambda: list()) # type: ignore
|
|
95
|
-
self._default_duri = default_dataspace_uri
|
|
96
94
|
self.ws = ws
|
|
97
95
|
|
|
98
96
|
self.timeout = timeout
|
|
99
|
-
self.client_info.endpoint_capabilities['MaxWebSocketMessagePayloadSize'] =
|
|
97
|
+
self.client_info.endpoint_capabilities['MaxWebSocketMessagePayloadSize'] = SETTINGS.MaxWebSocketMessagePayloadSize
|
|
100
98
|
self.__recvtask = asyncio.create_task(self.__recv__())
|
|
99
|
+
self.max_concurrent_requests = 1
|
|
101
100
|
|
|
102
101
|
#
|
|
103
102
|
# client
|
|
@@ -121,7 +120,7 @@ class ETPClient(ETPConnection):
|
|
|
121
120
|
# create future recv event
|
|
122
121
|
self._recv_events[msg.header.message_id] = asyncio.Event()
|
|
123
122
|
|
|
124
|
-
|
|
123
|
+
for msg_part in msg.encode_message_generator(self.max_size, self):
|
|
125
124
|
await self.ws.send(msg_part)
|
|
126
125
|
|
|
127
126
|
return msg.header.message_id
|
|
@@ -216,21 +215,22 @@ class ETPClient(ETPConnection):
|
|
|
216
215
|
|
|
217
216
|
async def request_session(self):
|
|
218
217
|
# Handshake protocol
|
|
219
|
-
|
|
218
|
+
etp_version = Version(major=1, minor=2, revision=0, patch=0)
|
|
220
219
|
msg = await self.send(
|
|
221
220
|
RequestSession(
|
|
222
221
|
applicationName=SETTINGS.application_name,
|
|
223
222
|
applicationVersion=SETTINGS.application_version,
|
|
224
223
|
clientInstanceId=uuid.uuid4(), # type: ignore
|
|
225
224
|
requestedProtocols=[
|
|
226
|
-
SupportedProtocol(protocol=p.value, protocolVersion=
|
|
227
|
-
for p in
|
|
225
|
+
SupportedProtocol(protocol=p.value, protocolVersion=etp_version, role='store')
|
|
226
|
+
for p in CommunicationProtocol
|
|
228
227
|
],
|
|
229
228
|
supportedDataObjects=[SupportedDataObject(qualifiedType="resqml20.*"), SupportedDataObject(qualifiedType="eml20.*")],
|
|
230
229
|
currentDateTime=self.timestamp,
|
|
231
230
|
earliestRetainedChangeTime=0,
|
|
232
231
|
endpointCapabilities=dict(
|
|
233
|
-
MaxWebSocketMessagePayloadSize=DataValue(item=self.max_size)
|
|
232
|
+
MaxWebSocketMessagePayloadSize=DataValue(item=self.max_size),
|
|
233
|
+
MaxWebSocketFramePayloadSize=DataValue(item=10000)
|
|
234
234
|
)
|
|
235
235
|
)
|
|
236
236
|
)
|
|
@@ -246,10 +246,7 @@ class ETPClient(ETPConnection):
|
|
|
246
246
|
|
|
247
247
|
async def authorize(self, authorization: str, supplemental_authorization: T.Mapping[str, str] = {}):
|
|
248
248
|
|
|
249
|
-
|
|
250
|
-
Authorize
|
|
251
|
-
from etptypes.energistics.etp.v12.protocol.core.authorize_response import \
|
|
252
|
-
AuthorizeResponse
|
|
249
|
+
|
|
253
250
|
|
|
254
251
|
msg = await self.send(
|
|
255
252
|
Authorize(
|
|
@@ -275,36 +272,28 @@ class ETPClient(ETPConnection):
|
|
|
275
272
|
def timestamp(self):
|
|
276
273
|
return int(datetime.datetime.now(datetime.timezone.utc).timestamp())
|
|
277
274
|
|
|
278
|
-
@property
|
|
279
|
-
def default_dataspace_uri(self):
|
|
280
|
-
return self._default_duri
|
|
281
|
-
|
|
282
|
-
@default_dataspace_uri.setter
|
|
283
|
-
def default_dataspace_uri(self, v: T.Union[DataspaceURI, str, None]):
|
|
284
|
-
self._default_duri = None if v is None else DataspaceURI.from_any(v)
|
|
285
|
-
|
|
286
|
-
def get_dataspace_or_default_uri(self, ds: T.Union[DataspaceURI, str, None]) -> DataspaceURI:
|
|
287
|
-
"""Returns default dataspace or user spefied one"""
|
|
288
|
-
|
|
289
|
-
if ds is not None:
|
|
290
|
-
return DataspaceURI.from_any(ds)
|
|
291
|
-
|
|
292
|
-
if self._default_duri is None:
|
|
293
|
-
raise ValueError("Could not get dataspace from userinput or default")
|
|
294
|
-
|
|
295
|
-
return self._default_duri
|
|
296
275
|
|
|
276
|
+
def dataspace_uri(self, ds: str) -> DataspaceURI:
|
|
277
|
+
return DataspaceURI.from_name(ds)
|
|
278
|
+
|
|
279
|
+
def list_objects(self, dataspace_uri: DataspaceURI, depth: int = 1) -> list:
|
|
280
|
+
return self.send(GetResources(
|
|
281
|
+
scope=ContextScopeKind.TARGETS_OR_SELF,
|
|
282
|
+
context=ContextInfo(
|
|
283
|
+
uri=dataspace_uri.raw_uri,
|
|
284
|
+
depth=depth,
|
|
285
|
+
dataObjectTypes=[],
|
|
286
|
+
navigableEdges=RelationshipKind.PRIMARY,)
|
|
287
|
+
)
|
|
288
|
+
)
|
|
297
289
|
#
|
|
298
290
|
# dataspace
|
|
299
291
|
#
|
|
300
292
|
|
|
301
|
-
async def put_dataspaces(self, *
|
|
302
|
-
from etptypes.energistics.etp.v12.protocol.dataspace.put_dataspaces import \
|
|
303
|
-
PutDataspaces
|
|
304
|
-
from etptypes.energistics.etp.v12.protocol.dataspace.put_dataspaces_response import \
|
|
305
|
-
PutDataspacesResponse
|
|
293
|
+
async def put_dataspaces(self, *dataspace_uris: DataspaceURI):
|
|
306
294
|
|
|
307
|
-
|
|
295
|
+
|
|
296
|
+
_uris = list(map(DataspaceURI.from_any, dataspace_uris))
|
|
308
297
|
|
|
309
298
|
time = self.timestamp
|
|
310
299
|
response = await self.send(
|
|
@@ -315,23 +304,20 @@ class ETPClient(ETPConnection):
|
|
|
315
304
|
)
|
|
316
305
|
assert isinstance(response, PutDataspacesResponse), "Expected PutDataspacesResponse"
|
|
317
306
|
|
|
318
|
-
assert len(response.success) == len(
|
|
307
|
+
assert len(response.success) == len(dataspace_uris), f"expected {len(dataspace_uris)} success's"
|
|
319
308
|
|
|
320
309
|
return response.success
|
|
321
310
|
|
|
322
|
-
async def put_dataspaces_no_raise(self, *
|
|
311
|
+
async def put_dataspaces_no_raise(self, *dataspace_uris: DataspaceURI):
|
|
323
312
|
try:
|
|
324
|
-
return await self.put_dataspaces(*
|
|
313
|
+
return await self.put_dataspaces(*dataspace_uris)
|
|
325
314
|
except ETPError:
|
|
326
315
|
pass
|
|
327
316
|
|
|
328
|
-
async def delete_dataspaces(self, *
|
|
329
|
-
from etptypes.energistics.etp.v12.protocol.dataspace.delete_dataspaces import \
|
|
330
|
-
DeleteDataspaces
|
|
331
|
-
from etptypes.energistics.etp.v12.protocol.dataspace.delete_dataspaces_response import \
|
|
332
|
-
DeleteDataspacesResponse
|
|
317
|
+
async def delete_dataspaces(self, *dataspace_uris: DataspaceURI):
|
|
333
318
|
|
|
334
|
-
|
|
319
|
+
|
|
320
|
+
_uris = list(map(str, dataspace_uris))
|
|
335
321
|
|
|
336
322
|
response = await self.send(DeleteDataspaces(uris=dict(zip(_uris, _uris))))
|
|
337
323
|
assert isinstance(response, DeleteDataspacesResponse), "Expected DeleteDataspacesResponse"
|
|
@@ -343,11 +329,6 @@ class ETPClient(ETPConnection):
|
|
|
343
329
|
|
|
344
330
|
async def get_data_objects(self, *uris: T.Union[DataObjectURI, str]):
|
|
345
331
|
|
|
346
|
-
from etptypes.energistics.etp.v12.protocol.store.get_data_objects import \
|
|
347
|
-
GetDataObjects
|
|
348
|
-
from etptypes.energistics.etp.v12.protocol.store.get_data_objects_response import \
|
|
349
|
-
GetDataObjectsResponse
|
|
350
|
-
|
|
351
332
|
_uris = list(map(str, uris))
|
|
352
333
|
|
|
353
334
|
msg = await self.send(
|
|
@@ -360,10 +341,7 @@ class ETPClient(ETPConnection):
|
|
|
360
341
|
|
|
361
342
|
async def put_data_objects(self, *objs: DataObject):
|
|
362
343
|
|
|
363
|
-
|
|
364
|
-
PutDataObjects
|
|
365
|
-
from etptypes.energistics.etp.v12.protocol.store.put_data_objects_response import \
|
|
366
|
-
PutDataObjectsResponse
|
|
344
|
+
|
|
367
345
|
|
|
368
346
|
response = await self.send(
|
|
369
347
|
PutDataObjects(dataObjects={f"{p.resource.name}_{short_id()}": p for p in objs})
|
|
@@ -378,12 +356,10 @@ class ETPClient(ETPConnection):
|
|
|
378
356
|
data_objects = await self.get_data_objects(*uris)
|
|
379
357
|
return utils_xml.parse_resqml_objects(data_objects)
|
|
380
358
|
|
|
381
|
-
async def put_resqml_objects(self, *objs: ro.AbstractObject,
|
|
382
|
-
|
|
383
|
-
Resource
|
|
359
|
+
async def put_resqml_objects(self, *objs: ro.AbstractObject, dataspace_uri: DataspaceURI):
|
|
360
|
+
|
|
384
361
|
time = self.timestamp
|
|
385
|
-
|
|
386
|
-
uris = [DataObjectURI.from_obj(duri, obj) for obj in objs]
|
|
362
|
+
uris = [DataObjectURI.from_obj(dataspace_uri, obj) for obj in objs]
|
|
387
363
|
dobjs = [DataObject(
|
|
388
364
|
format="xml",
|
|
389
365
|
data=utils_xml.resqml_to_xml(obj),
|
|
@@ -403,10 +379,7 @@ class ETPClient(ETPConnection):
|
|
|
403
379
|
return uris
|
|
404
380
|
|
|
405
381
|
async def delete_data_objects(self, *uris: T.Union[DataObjectURI, str], pruneContainedObjects=False):
|
|
406
|
-
|
|
407
|
-
DeleteDataObjects
|
|
408
|
-
from etptypes.energistics.etp.v12.protocol.store.delete_data_objects_response import \
|
|
409
|
-
DeleteDataObjectsResponse
|
|
382
|
+
|
|
410
383
|
|
|
411
384
|
_uris = list(map(str, uris))
|
|
412
385
|
|
|
@@ -420,7 +393,6 @@ class ETPClient(ETPConnection):
|
|
|
420
393
|
assert isinstance(response, DeleteDataObjectsResponse), "Expected DeleteDataObjectsResponse"
|
|
421
394
|
|
|
422
395
|
return response.deleted_uris
|
|
423
|
-
|
|
424
396
|
#
|
|
425
397
|
# xtgeo
|
|
426
398
|
#
|
|
@@ -446,7 +418,7 @@ class ETPClient(ETPConnection):
|
|
|
446
418
|
y_ind = (y-patch.geometry.points.supporting_geometry.origin.coordinate2)/patch.geometry.points.supporting_geometry.offset[1].spacing.value
|
|
447
419
|
return round(x_ind), round(y_ind)
|
|
448
420
|
|
|
449
|
-
async def get_surface_value_x_y(self, epc_uri: T.Union[DataObjectURI, str], gri_uri: T.Union[DataObjectURI, str], x: T.Union[int, float], y: T.Union[int, float], method: T.Literal["bilinear", "nearest"]):
|
|
421
|
+
async def get_surface_value_x_y(self, epc_uri: T.Union[DataObjectURI, str], gri_uri: T.Union[DataObjectURI, str],crs_uri: T.Union[DataObjectURI, str], x: T.Union[int, float], y: T.Union[int, float], method: T.Literal["bilinear", "nearest"]):
|
|
450
422
|
gri, = await self.get_resqml_objects(gri_uri) # parallelized using subarray
|
|
451
423
|
xori = gri.grid2d_patch.geometry.points.supporting_geometry.origin.coordinate1
|
|
452
424
|
yori = gri.grid2d_patch.geometry.points.supporting_geometry.origin.coordinate2
|
|
@@ -462,7 +434,7 @@ class ETPClient(ETPConnection):
|
|
|
462
434
|
uri=str(epc_uri), pathInResource=gri.grid2d_patch.geometry.points.zvalues.values.path_in_hdf_file
|
|
463
435
|
)
|
|
464
436
|
if max_x_index_in_gri <= 10 or max_y_index_in_gri <= 10:
|
|
465
|
-
surf = await self.get_xtgeo_surface(epc_uri, gri_uri)
|
|
437
|
+
surf = await self.get_xtgeo_surface(epc_uri, gri_uri, crs_uri)
|
|
466
438
|
return surf.get_value_from_xy((x, y), sampling=method)
|
|
467
439
|
|
|
468
440
|
x_ind, y_ind = self.find_closest_index(x, y, gri.grid2d_patch)
|
|
@@ -499,21 +471,12 @@ class ETPClient(ETPConnection):
|
|
|
499
471
|
)
|
|
500
472
|
return regridded.get_value_from_xy((x, y))
|
|
501
473
|
|
|
502
|
-
async def get_xtgeo_surface(self, epc_uri: T.Union[DataObjectURI, str], gri_uri: T.Union[DataObjectURI, str], crs_uri: T.Union[DataObjectURI, str
|
|
503
|
-
|
|
504
|
-
logger.debug("NO crs")
|
|
505
|
-
gri, = await self.get_resqml_objects(gri_uri)
|
|
506
|
-
crs_uuid = gri.grid2d_patch.geometry.local_crs.uuid
|
|
507
|
-
dataspace_uri = self.get_dataspace_or_default_uri(epc_uri)
|
|
508
|
-
crs_eml = f"{dataspace_uri}/resqml20.LocalDepth3dCrs({crs_uuid})"
|
|
509
|
-
crs, = await self.get_resqml_objects(crs_eml)
|
|
510
|
-
logger.debug("got crs")
|
|
511
|
-
else:
|
|
512
|
-
gri, crs, = await self.get_resqml_objects(gri_uri, crs_uri)
|
|
474
|
+
async def get_xtgeo_surface(self, epc_uri: T.Union[DataObjectURI, str], gri_uri: T.Union[DataObjectURI, str], crs_uri: T.Union[DataObjectURI, str]):
|
|
475
|
+
gri, crs, = await self.get_resqml_objects(gri_uri, crs_uri)
|
|
513
476
|
rotation = crs.areal_rotation.value
|
|
514
477
|
# some checks
|
|
515
478
|
|
|
516
|
-
assert isinstance(gri, ro.Grid2dRepresentation), "obj must be
|
|
479
|
+
assert isinstance(gri, ro.Grid2dRepresentation), "obj must be Grid2DRepresentation"
|
|
517
480
|
sgeo = gri.grid2d_patch.geometry.points.supporting_geometry # type: ignore
|
|
518
481
|
if sys.version_info[1] != 10:
|
|
519
482
|
assert isinstance(gri.grid2d_patch.geometry.points, ro.Point3dZValueArray), "Points must be Point3dZValueArray"
|
|
@@ -537,13 +500,28 @@ class ETPClient(ETPConnection):
|
|
|
537
500
|
rotation=rotation,
|
|
538
501
|
masked=True
|
|
539
502
|
)
|
|
540
|
-
|
|
541
|
-
|
|
503
|
+
async def start_transaction(self, dataspace_uri: DataspaceURI, readOnly :bool= True) -> uuid.UUID:
|
|
504
|
+
trans_id = await self.send(StartTransaction(readOnly=readOnly, dataspaceUris=[dataspace_uri.raw_uri]))
|
|
505
|
+
if trans_id.successful is False:
|
|
506
|
+
raise Exception(f"Failed starting transaction {dataspace_uri.raw_uri}")
|
|
507
|
+
return uuid.UUID(bytes=trans_id.transaction_uuid)
|
|
508
|
+
|
|
509
|
+
async def commit_transaction(self, transaction_id: uuid.UUID):
|
|
510
|
+
r = await self.send(CommitTransaction(transaction_uuid=transaction_id))
|
|
511
|
+
if r.successful is False:
|
|
512
|
+
raise Exception(r.failure_reason)
|
|
513
|
+
return r
|
|
514
|
+
|
|
515
|
+
async def rollback_transaction(self, transaction_id: uuid.UUID):
|
|
516
|
+
return await self.send(RollbackTransaction(transactionUuid=transaction_id))
|
|
517
|
+
|
|
518
|
+
async def put_xtgeo_surface(self, surface: RegularSurface, epsg_code: int, dataspace_uri: DataspaceURI):
|
|
542
519
|
"""Returns (epc_uri, crs_uri, gri_uri)"""
|
|
543
520
|
assert surface.values is not None, "cannot upload empty surface"
|
|
544
|
-
|
|
521
|
+
|
|
522
|
+
|
|
545
523
|
epc, crs, gri = utils_xml.parse_xtgeo_surface_to_resqml_grid(surface, epsg_code)
|
|
546
|
-
epc_uri, crs_uri, gri_uri = await self.put_resqml_objects(epc, crs, gri,
|
|
524
|
+
epc_uri, crs_uri, gri_uri = await self.put_resqml_objects(epc, crs, gri, dataspace_uri=dataspace_uri)
|
|
547
525
|
response = await self.put_array(
|
|
548
526
|
DataArrayIdentifier(
|
|
549
527
|
uri=epc_uri.raw_uri if isinstance(epc_uri, DataObjectURI) else epc_uri,
|
|
@@ -552,7 +530,7 @@ class ETPClient(ETPConnection):
|
|
|
552
530
|
surface.values.filled(np.nan).astype(np.float32)
|
|
553
531
|
)
|
|
554
532
|
|
|
555
|
-
return epc_uri,
|
|
533
|
+
return epc_uri, gri_uri, crs_uri
|
|
556
534
|
|
|
557
535
|
#
|
|
558
536
|
# resqpy meshes
|
|
@@ -562,7 +540,7 @@ class ETPClient(ETPConnection):
|
|
|
562
540
|
uns, = await self.get_resqml_objects(uns_uri)
|
|
563
541
|
|
|
564
542
|
# some checks
|
|
565
|
-
assert isinstance(uns, ro.UnstructuredGridRepresentation), "obj must be
|
|
543
|
+
assert isinstance(uns, ro.UnstructuredGridRepresentation), "obj must be UnstructuredGridRepresentation"
|
|
566
544
|
assert isinstance(uns.geometry, ro.UnstructuredGridGeometry), "geometry must be UnstructuredGridGeometry"
|
|
567
545
|
if sys.version_info[1] != 10:
|
|
568
546
|
assert isinstance(uns.geometry.points, ro.Point3dHdf5Array), "points must be Point3dHdf5Array"
|
|
@@ -706,14 +684,15 @@ class ETPClient(ETPConnection):
|
|
|
706
684
|
async def put_rddms_property(self, epc_uri: T.Union[DataObjectURI , str],
|
|
707
685
|
cprop0: T.Union[ro.ContinuousProperty, ro.DiscreteProperty],
|
|
708
686
|
propertykind0: ro.PropertyKind,
|
|
709
|
-
array_ref: np.ndarray,
|
|
687
|
+
array_ref: np.ndarray,
|
|
688
|
+
dataspace_uri: DataspaceURI ):
|
|
710
689
|
|
|
711
690
|
assert isinstance(cprop0, ro.ContinuousProperty) or isinstance(cprop0, ro.DiscreteProperty), "prop must be a Property"
|
|
712
691
|
assert len(cprop0.patch_of_values) == 1, "property obj must have exactly one patch of values"
|
|
713
692
|
|
|
714
693
|
st = time.time()
|
|
715
|
-
propkind_uri = [""] if (propertykind0 is None) else (await self.put_resqml_objects(propertykind0,
|
|
716
|
-
cprop_uri = await self.put_resqml_objects(cprop0,
|
|
694
|
+
propkind_uri = [""] if (propertykind0 is None) else (await self.put_resqml_objects(propertykind0, dataspace_uri=dataspace_uri))
|
|
695
|
+
cprop_uri = await self.put_resqml_objects(cprop0, dataspace_uri=dataspace_uri)
|
|
717
696
|
delay = time.time() - st
|
|
718
697
|
logger.debug(f"pyetp: put_rddms_property: put objects took {delay} s")
|
|
719
698
|
|
|
@@ -731,13 +710,13 @@ class ETPClient(ETPConnection):
|
|
|
731
710
|
|
|
732
711
|
async def put_epc_mesh(
|
|
733
712
|
self, epc_filename: str, title_in: str, property_titles: T.List[str], projected_epsg: int,
|
|
734
|
-
|
|
713
|
+
dataspace_uri: DataspaceURI
|
|
735
714
|
):
|
|
736
715
|
uns, crs, epc, timeseries, hexa = utils_xml.convert_epc_mesh_to_resqml_mesh(epc_filename, title_in, projected_epsg)
|
|
737
|
-
epc_uri, crs_uri, uns_uri = await self.put_resqml_objects(epc, crs, uns,
|
|
716
|
+
epc_uri, crs_uri, uns_uri = await self.put_resqml_objects(epc, crs, uns, dataspace_uri=dataspace_uri)
|
|
738
717
|
timeseries_uri = ""
|
|
739
718
|
if timeseries is not None:
|
|
740
|
-
timeseries_uris = await self.put_resqml_objects(timeseries,
|
|
719
|
+
timeseries_uris = await self.put_resqml_objects(timeseries, dataspace_uri=dataspace_uri)
|
|
741
720
|
timeseries_uri = list(timeseries_uris)[0] if (len(list(timeseries_uris)) > 0) else ""
|
|
742
721
|
|
|
743
722
|
#
|
|
@@ -808,7 +787,7 @@ class ETPClient(ETPConnection):
|
|
|
808
787
|
|
|
809
788
|
cprop_uris = []
|
|
810
789
|
for cprop0, prop, time_index in zip(cprop0s, props, time_indices):
|
|
811
|
-
cprop_uri, propkind_uri = await self.put_rddms_property(epc_uri, cprop0, propertykind0, prop.array_ref(),
|
|
790
|
+
cprop_uri, propkind_uri = await self.put_rddms_property(epc_uri, cprop0, propertykind0, prop.array_ref(), dataspace_uri)
|
|
812
791
|
cprop_uris.extend(cprop_uri)
|
|
813
792
|
prop_rddms_uris[propname] = [propkind_uri, cprop_uris]
|
|
814
793
|
|
|
@@ -881,10 +860,7 @@ class ETPClient(ETPConnection):
|
|
|
881
860
|
#
|
|
882
861
|
|
|
883
862
|
async def get_array_metadata(self, *uids: DataArrayIdentifier):
|
|
884
|
-
|
|
885
|
-
GetDataArrayMetadata
|
|
886
|
-
from etptypes.energistics.etp.v12.protocol.data_array.get_data_array_metadata_response import \
|
|
887
|
-
GetDataArrayMetadataResponse
|
|
863
|
+
|
|
888
864
|
|
|
889
865
|
response = await self.send(
|
|
890
866
|
GetDataArrayMetadata(dataArrays={i.path_in_resource: i for i in uids})
|
|
@@ -898,10 +874,7 @@ class ETPClient(ETPConnection):
|
|
|
898
874
|
return [response.array_metadata[i.path_in_resource] for i in uids]
|
|
899
875
|
|
|
900
876
|
async def get_array(self, uid: DataArrayIdentifier):
|
|
901
|
-
|
|
902
|
-
GetDataArrays
|
|
903
|
-
from etptypes.energistics.etp.v12.protocol.data_array.get_data_arrays_response import \
|
|
904
|
-
GetDataArraysResponse
|
|
877
|
+
|
|
905
878
|
|
|
906
879
|
# Check if we can upload the full array in one go.
|
|
907
880
|
meta, = await self.get_array_metadata(uid)
|
|
@@ -917,12 +890,7 @@ class ETPClient(ETPConnection):
|
|
|
917
890
|
return utils_arrays.to_numpy(arrays[0])
|
|
918
891
|
|
|
919
892
|
async def put_array(self, uid: DataArrayIdentifier, data: np.ndarray):
|
|
920
|
-
|
|
921
|
-
PutDataArraysType
|
|
922
|
-
from etptypes.energistics.etp.v12.protocol.data_array.put_data_arrays import \
|
|
923
|
-
PutDataArrays
|
|
924
|
-
from etptypes.energistics.etp.v12.protocol.data_array.put_data_arrays_response import \
|
|
925
|
-
PutDataArraysResponse
|
|
893
|
+
|
|
926
894
|
|
|
927
895
|
# Check if we can upload the full array in one go.
|
|
928
896
|
if data.nbytes > self.max_array_size:
|
|
@@ -940,12 +908,7 @@ class ETPClient(ETPConnection):
|
|
|
940
908
|
starts = np.array(starts).astype(np.int64)
|
|
941
909
|
counts = np.array(counts).astype(np.int64)
|
|
942
910
|
|
|
943
|
-
|
|
944
|
-
GetDataSubarraysType
|
|
945
|
-
from etptypes.energistics.etp.v12.protocol.data_array.get_data_subarrays import \
|
|
946
|
-
GetDataSubarrays
|
|
947
|
-
from etptypes.energistics.etp.v12.protocol.data_array.get_data_subarrays_response import \
|
|
948
|
-
GetDataSubarraysResponse
|
|
911
|
+
|
|
949
912
|
|
|
950
913
|
logger.debug(f"get_subarray {starts=:} {counts=:}")
|
|
951
914
|
|
|
@@ -962,22 +925,15 @@ class ETPClient(ETPConnection):
|
|
|
962
925
|
arrays = list(response.data_subarrays.values())
|
|
963
926
|
return utils_arrays.to_numpy(arrays[0])
|
|
964
927
|
|
|
965
|
-
async def put_subarray(self, uid: DataArrayIdentifier, data: np.ndarray, starts: T.Union[np.ndarray, T.List[int]], counts: T.Union[np.ndarray, T.List[int]]
|
|
966
|
-
|
|
967
|
-
PutDataSubarraysType
|
|
968
|
-
from etptypes.energistics.etp.v12.protocol.data_array.put_data_subarrays import \
|
|
969
|
-
PutDataSubarrays
|
|
970
|
-
from etptypes.energistics.etp.v12.protocol.data_array.put_data_subarrays_response import \
|
|
971
|
-
PutDataSubarraysResponse
|
|
928
|
+
async def put_subarray(self, uid: DataArrayIdentifier, data: np.ndarray, starts: T.Union[np.ndarray, T.List[int]], counts: T.Union[np.ndarray, T.List[int]]):
|
|
929
|
+
|
|
972
930
|
|
|
973
931
|
# starts [start_X, starts_Y]
|
|
974
932
|
# counts [count_X, count_Y]
|
|
975
933
|
starts = np.array(starts).astype(np.int64) # len = 2 [x_start_index, y_start_index]
|
|
976
934
|
counts = np.array(counts).astype(np.int64) # len = 2
|
|
977
935
|
ends = starts + counts # len = 2
|
|
978
|
-
|
|
979
|
-
transport_array_type = utils_arrays.get_transport(data.dtype)
|
|
980
|
-
await self._put_uninitialized_data_array(uid, data.shape, transport_array_type=transport_array_type)
|
|
936
|
+
|
|
981
937
|
|
|
982
938
|
slices = tuple(map(lambda se: slice(se[0], se[1]), zip(starts, ends)))
|
|
983
939
|
dataarray = utils_arrays.to_data_array(data[slices])
|
|
@@ -994,7 +950,6 @@ class ETPClient(ETPConnection):
|
|
|
994
950
|
PutDataSubarrays(dataSubarrays={uid.path_in_resource: payload})
|
|
995
951
|
)
|
|
996
952
|
assert isinstance(response, PutDataSubarraysResponse), "Expected PutDataSubarraysResponse"
|
|
997
|
-
|
|
998
953
|
assert len(response.success) == 1, "expected one success"
|
|
999
954
|
return response.success
|
|
1000
955
|
|
|
@@ -1049,11 +1004,14 @@ class ETPClient(ETPConnection):
|
|
|
1049
1004
|
slices = tuple(map(lambda se: slice(se[0], se[1]), zip(starts-offset, ends-offset)))
|
|
1050
1005
|
buffer[slices] = array
|
|
1051
1006
|
return
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1007
|
+
coro = [populate(starts, counts) for starts, counts in self._get_chunk_sizes(buffer_shape, dtype, offset)]
|
|
1008
|
+
logger.debug(f"Concurrent request: {self.max_concurrent_requests}")
|
|
1009
|
+
for i in batched(coro, self.max_concurrent_requests):
|
|
1010
|
+
await asyncio.gather(*i)
|
|
1011
|
+
# r = await asyncio.gather(*[
|
|
1012
|
+
# populate(starts, counts)
|
|
1013
|
+
# for starts, counts in self._get_chunk_sizes(buffer_shape, dtype, offset)
|
|
1014
|
+
# ])
|
|
1057
1015
|
|
|
1058
1016
|
return buffer
|
|
1059
1017
|
|
|
@@ -1065,18 +1023,17 @@ class ETPClient(ETPConnection):
|
|
|
1065
1023
|
coro = []
|
|
1066
1024
|
for starts, counts in self._get_chunk_sizes(data.shape, data.dtype):
|
|
1067
1025
|
params.append([starts, counts])
|
|
1026
|
+
#await self.put_subarray(uid, data, starts, counts)
|
|
1068
1027
|
coro.append(self.put_subarray(uid, data, starts, counts))
|
|
1069
|
-
|
|
1028
|
+
logger.debug(f"Concurrent request: {self.max_concurrent_requests}")
|
|
1029
|
+
for i in batched(coro, self.max_concurrent_requests):
|
|
1030
|
+
await asyncio.gather(*i)
|
|
1031
|
+
#r = await asyncio.gather(*coro)
|
|
1070
1032
|
|
|
1071
1033
|
return {uid.uri: ''}
|
|
1072
1034
|
|
|
1073
1035
|
async def _put_uninitialized_data_array(self, uid: DataArrayIdentifier, shape: T.Tuple[int, ...], transport_array_type=AnyArrayType.ARRAY_OF_FLOAT, logical_array_type=AnyLogicalArrayType.ARRAY_OF_BOOLEAN):
|
|
1074
|
-
|
|
1075
|
-
PutUninitializedDataArrayType
|
|
1076
|
-
from etptypes.energistics.etp.v12.protocol.data_array.put_uninitialized_data_arrays import \
|
|
1077
|
-
PutUninitializedDataArrays
|
|
1078
|
-
from etptypes.energistics.etp.v12.protocol.data_array.put_uninitialized_data_arrays_response import \
|
|
1079
|
-
PutUninitializedDataArraysResponse
|
|
1036
|
+
|
|
1080
1037
|
|
|
1081
1038
|
payload = PutUninitializedDataArrayType(
|
|
1082
1039
|
uid=uid,
|
|
@@ -1104,7 +1061,6 @@ class connect:
|
|
|
1104
1061
|
self.authorization = authorization
|
|
1105
1062
|
self.data_partition = SETTINGS.data_partition
|
|
1106
1063
|
self.timeout = SETTINGS.etp_timeout
|
|
1107
|
-
self.default_dataspace_uri = DataspaceURI.from_name(SETTINGS.dataspace)
|
|
1108
1064
|
|
|
1109
1065
|
# ... = await connect(...)
|
|
1110
1066
|
|
|
@@ -1127,12 +1083,12 @@ class connect:
|
|
|
1127
1083
|
self.server_url,
|
|
1128
1084
|
subprotocols=[ETPClient.SUB_PROTOCOL], # type: ignore
|
|
1129
1085
|
extra_headers=headers,
|
|
1130
|
-
max_size=
|
|
1086
|
+
max_size=SETTINGS.MaxWebSocketMessagePayloadSize,
|
|
1131
1087
|
ping_timeout=self.timeout,
|
|
1132
1088
|
open_timeout=None,
|
|
1133
1089
|
)
|
|
1134
1090
|
|
|
1135
|
-
self.client = ETPClient(ws,
|
|
1091
|
+
self.client = ETPClient(ws, timeout=self.timeout)
|
|
1136
1092
|
|
|
1137
1093
|
try:
|
|
1138
1094
|
await self.client.request_session()
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
|
-
from pydantic import AnyUrl, BaseSettings, Field
|
|
4
|
-
|
|
5
|
-
from pyetp.uri import DataspaceURI
|
|
3
|
+
from pydantic import AnyUrl, BaseSettings, Field
|
|
6
4
|
|
|
7
5
|
|
|
8
6
|
class WebSocketUrl(AnyUrl):
|
|
@@ -18,17 +16,14 @@ class Settings(BaseSettings):
|
|
|
18
16
|
'redis_password': {'env': ['redis_password', 'redispass']}
|
|
19
17
|
}
|
|
20
18
|
|
|
21
|
-
application_name: str = Field(default='
|
|
22
|
-
application_version: str = Field(default='0.0.
|
|
19
|
+
application_name: str = Field(default='pyetp')
|
|
20
|
+
application_version: str = Field(default='0.0.33')
|
|
23
21
|
|
|
24
|
-
dataspace: str = Field(default='demo/pss-data-gateway')
|
|
22
|
+
#dataspace: str = Field(default='demo/pss-data-gateway')
|
|
25
23
|
etp_url: WebSocketUrl = Field(default='wss://host.com')
|
|
26
|
-
etp_timeout: float = Field(default=
|
|
24
|
+
etp_timeout: float = Field(default=15., description="Timeout in seconds")
|
|
27
25
|
data_partition: Optional[str] = None
|
|
28
|
-
|
|
29
|
-
@property
|
|
30
|
-
def duri(self):
|
|
31
|
-
return DataspaceURI.from_name(self.dataspace)
|
|
26
|
+
MaxWebSocketMessagePayloadSize: int = Field(default=100000)
|
|
32
27
|
|
|
33
28
|
|
|
34
29
|
SETTINGS = Settings()
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
|
|
2
|
+
from etptypes import ETPModel
|
|
3
|
+
from etptypes.energistics.etp.v12.datatypes.any_array import AnyArray
|
|
4
|
+
from etptypes.energistics.etp.v12.datatypes.any_array_type import AnyArrayType
|
|
5
|
+
from etptypes.energistics.etp.v12.datatypes.any_logical_array_type import \
|
|
6
|
+
AnyLogicalArrayType
|
|
7
|
+
from etptypes.energistics.etp.v12.datatypes.array_of_boolean import \
|
|
8
|
+
ArrayOfBoolean
|
|
9
|
+
from etptypes.energistics.etp.v12.datatypes.array_of_double import \
|
|
10
|
+
ArrayOfDouble
|
|
11
|
+
from etptypes.energistics.etp.v12.datatypes.array_of_float import ArrayOfFloat
|
|
12
|
+
from etptypes.energistics.etp.v12.datatypes.array_of_int import ArrayOfInt
|
|
13
|
+
from etptypes.energistics.etp.v12.datatypes.array_of_long import ArrayOfLong
|
|
14
|
+
from etptypes.energistics.etp.v12.datatypes.data_array_types.data_array import \
|
|
15
|
+
DataArray
|
|
16
|
+
from etptypes.energistics.etp.v12.datatypes.data_array_types.data_array_identifier import \
|
|
17
|
+
DataArrayIdentifier
|
|
18
|
+
from etptypes.energistics.etp.v12.datatypes.data_array_types.data_array_metadata import \
|
|
19
|
+
DataArrayMetadata
|
|
20
|
+
from etptypes.energistics.etp.v12.datatypes.data_value import DataValue
|
|
21
|
+
from etptypes.energistics.etp.v12.datatypes.error_info import ErrorInfo
|
|
22
|
+
from etptypes.energistics.etp.v12.datatypes.message_header import MessageHeader
|
|
23
|
+
from etptypes.energistics.etp.v12.datatypes.object.data_object import \
|
|
24
|
+
DataObject
|
|
25
|
+
from etptypes.energistics.etp.v12.datatypes.object.dataspace import Dataspace
|
|
26
|
+
from etptypes.energistics.etp.v12.datatypes.server_capabilities import \
|
|
27
|
+
ServerCapabilities
|
|
28
|
+
from etptypes.energistics.etp.v12.datatypes.supported_data_object import \
|
|
29
|
+
SupportedDataObject
|
|
30
|
+
from etptypes.energistics.etp.v12.datatypes.supported_protocol import \
|
|
31
|
+
SupportedProtocol
|
|
32
|
+
from etptypes.energistics.etp.v12.datatypes.version import Version
|
|
33
|
+
from etptypes.energistics.etp.v12.protocol.core.acknowledge import Acknowledge
|
|
34
|
+
from etptypes.energistics.etp.v12.protocol.core.authorize import Authorize
|
|
35
|
+
from etptypes.energistics.etp.v12.protocol.core.authorize_response import \
|
|
36
|
+
AuthorizeResponse
|
|
37
|
+
from etptypes.energistics.etp.v12.protocol.core.close_session import \
|
|
38
|
+
CloseSession
|
|
39
|
+
from etptypes.energistics.etp.v12.protocol.core.open_session import OpenSession
|
|
40
|
+
from etptypes.energistics.etp.v12.protocol.core.protocol_exception import \
|
|
41
|
+
ProtocolException
|
|
42
|
+
from etptypes.energistics.etp.v12.protocol.core.request_session import \
|
|
43
|
+
RequestSession
|
|
44
|
+
from etptypes.energistics.etp.v12.protocol.transaction.start_transaction import StartTransaction
|
|
45
|
+
from etptypes.energistics.etp.v12.protocol.transaction.commit_transaction import CommitTransaction
|
|
46
|
+
from etptypes.energistics.etp.v12.protocol.transaction.rollback_transaction import RollbackTransaction
|
|
47
|
+
from etptypes.energistics.etp.v12.datatypes.data_array_types.put_data_subarrays_type import \
|
|
48
|
+
PutDataSubarraysType
|
|
49
|
+
from etptypes.energistics.etp.v12.datatypes.object.relationship_kind import RelationshipKind
|
|
50
|
+
from etptypes.energistics.etp.v12.datatypes.object.context_info import ContextInfo
|
|
51
|
+
from etptypes.energistics.etp.v12.protocol.data_array.put_data_subarrays import \
|
|
52
|
+
PutDataSubarrays
|
|
53
|
+
from etptypes.energistics.etp.v12.datatypes.object.context_scope_kind import ContextScopeKind
|
|
54
|
+
from etptypes.energistics.etp.v12.protocol.data_array.put_data_subarrays_response import \
|
|
55
|
+
PutDataSubarraysResponse
|
|
56
|
+
from etptypes.energistics.etp.v12.datatypes.data_array_types.get_data_subarrays_type import \
|
|
57
|
+
GetDataSubarraysType
|
|
58
|
+
from etptypes.energistics.etp.v12.protocol.data_array.get_data_subarrays import \
|
|
59
|
+
GetDataSubarrays
|
|
60
|
+
from etptypes.energistics.etp.v12.protocol.data_array.get_data_subarrays_response import \
|
|
61
|
+
GetDataSubarraysResponse
|
|
62
|
+
from etptypes.energistics.etp.v12.datatypes.data_array_types.put_data_arrays_type import \
|
|
63
|
+
PutDataArraysType
|
|
64
|
+
from etptypes.energistics.etp.v12.protocol.data_array.put_data_arrays import \
|
|
65
|
+
PutDataArrays
|
|
66
|
+
from etptypes.energistics.etp.v12.protocol.data_array.put_data_arrays_response import \
|
|
67
|
+
PutDataArraysResponse
|
|
68
|
+
from etptypes.energistics.etp.v12.protocol.data_array.get_data_arrays import \
|
|
69
|
+
GetDataArrays
|
|
70
|
+
from etptypes.energistics.etp.v12.protocol.data_array.get_data_arrays_response import \
|
|
71
|
+
GetDataArraysResponse
|
|
72
|
+
from etptypes.energistics.etp.v12.protocol.data_array.get_data_array_metadata import \
|
|
73
|
+
GetDataArrayMetadata
|
|
74
|
+
from etptypes.energistics.etp.v12.protocol.data_array.get_data_array_metadata_response import \
|
|
75
|
+
GetDataArrayMetadataResponse
|
|
76
|
+
from etptypes.energistics.etp.v12.datatypes.data_array_types.put_uninitialized_data_array_type import \
|
|
77
|
+
PutUninitializedDataArrayType
|
|
78
|
+
from etptypes.energistics.etp.v12.protocol.data_array.put_uninitialized_data_arrays import \
|
|
79
|
+
PutUninitializedDataArrays
|
|
80
|
+
from etptypes.energistics.etp.v12.protocol.data_array.put_uninitialized_data_arrays_response import \
|
|
81
|
+
PutUninitializedDataArraysResponse
|
|
82
|
+
from etptypes.energistics.etp.v12.protocol.store.delete_data_objects import \
|
|
83
|
+
DeleteDataObjects
|
|
84
|
+
from etptypes.energistics.etp.v12.protocol.store.delete_data_objects_response import \
|
|
85
|
+
DeleteDataObjectsResponse
|
|
86
|
+
from etptypes.energistics.etp.v12.datatypes.object.resource import \
|
|
87
|
+
Resource
|
|
88
|
+
from etptypes.energistics.etp.v12.protocol.discovery.get_resources import \
|
|
89
|
+
GetResources
|
|
90
|
+
from etptypes.energistics.etp.v12.protocol.store.put_data_objects import \
|
|
91
|
+
PutDataObjects
|
|
92
|
+
from etptypes.energistics.etp.v12.protocol.store.put_data_objects_response import \
|
|
93
|
+
PutDataObjectsResponse
|
|
94
|
+
from etptypes.energistics.etp.v12.protocol.store.get_data_objects import \
|
|
95
|
+
GetDataObjects
|
|
96
|
+
from etptypes.energistics.etp.v12.protocol.store.get_data_objects_response import \
|
|
97
|
+
GetDataObjectsResponse
|
|
98
|
+
from etptypes.energistics.etp.v12.protocol.dataspace.delete_dataspaces import \
|
|
99
|
+
DeleteDataspaces
|
|
100
|
+
from etptypes.energistics.etp.v12.protocol.dataspace.delete_dataspaces_response import \
|
|
101
|
+
DeleteDataspacesResponse
|
|
102
|
+
from etptypes.energistics.etp.v12.protocol.dataspace.put_dataspaces import \
|
|
103
|
+
PutDataspaces
|
|
104
|
+
from etptypes.energistics.etp.v12.protocol.dataspace.put_dataspaces_response import \
|
|
105
|
+
PutDataspacesResponse
|
|
106
|
+
from etptypes.energistics.etp.v12.protocol.core.authorize import \
|
|
107
|
+
Authorize
|
|
108
|
+
from etptypes.energistics.etp.v12.protocol.core.authorize_response import \
|
|
109
|
+
AuthorizeResponse
|
|
110
|
+
#
|
|
111
|
+
# NOTE we want to `from etptypes.energistics.etp.v12 import datatypes, protocol` and use this
|
|
112
|
+
# however this not supported with pylance as of yet, hence so many imports are reexported here
|
|
113
|
+
#
|
|
@@ -4,12 +4,11 @@ from uuid import UUID
|
|
|
4
4
|
from etpproto.uri import DataObjectURI as _DataObjectURI
|
|
5
5
|
from etpproto.uri import DataspaceUri as _DataspaceURI
|
|
6
6
|
from pydantic import BaseConfig
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
from pyetp.resqml_objects import AbstractObject
|
|
8
|
+
#from energyml.eml.v2_0.commonv2 import AbstractObject
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class _Mixin:
|
|
12
|
-
# print full url as default
|
|
13
12
|
raw_uri: str
|
|
14
13
|
|
|
15
14
|
def __str__(self):
|
|
@@ -66,7 +65,7 @@ class DataObjectURI(_DataObjectURI, _Mixin):
|
|
|
66
65
|
return cls(f"{duri}/{domain_and_version}.{obj_type}({uuid})")
|
|
67
66
|
|
|
68
67
|
@classmethod
|
|
69
|
-
def from_obj(cls, dataspace: Union[DataspaceURI , str], obj:
|
|
68
|
+
def from_obj(cls, dataspace: Union[DataspaceURI , str], obj: AbstractObject):
|
|
70
69
|
|
|
71
70
|
objname = obj.__class__.__name__
|
|
72
71
|
if getattr(obj, 'Meta', None):
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import random
|
|
2
|
+
import string
|
|
3
|
+
from itertools import islice
|
|
4
|
+
from typing import Iterable
|
|
5
|
+
def short_id(length=8):
|
|
6
|
+
return ''.join([random.choice(string.ascii_letters + string.digits + '-_') for _ in range(length)])
|
|
7
|
+
|
|
8
|
+
def batched(iterable:Iterable, n: int):
|
|
9
|
+
"Batch data into tuples of length n. The last batch may be shorter."
|
|
10
|
+
# batched('ABCDEFG', 3) --> ABC DEF G
|
|
11
|
+
if n < 1:
|
|
12
|
+
raise ValueError('n must be at least one')
|
|
13
|
+
it = iter(iterable)
|
|
14
|
+
while batch := tuple(islice(it, n)):
|
|
15
|
+
yield batch
|
|
@@ -2,15 +2,21 @@ import datetime
|
|
|
2
2
|
import logging
|
|
3
3
|
import typing as T
|
|
4
4
|
from uuid import uuid4
|
|
5
|
-
|
|
5
|
+
import numpy as np
|
|
6
6
|
import lxml.etree as ET
|
|
7
7
|
from xsdata.formats.dataclass.context import XmlContext
|
|
8
8
|
from xsdata.formats.dataclass.parsers import XmlParser
|
|
9
9
|
from xsdata.formats.dataclass.serializers import XmlSerializer
|
|
10
10
|
from xsdata.formats.dataclass.serializers.config import SerializerConfig
|
|
11
11
|
from xsdata.models.datatype import XmlDateTime
|
|
12
|
+
import resqpy.model as rq
|
|
13
|
+
import resqpy.time_series as rts
|
|
14
|
+
import resqpy.unstructured as rug
|
|
12
15
|
|
|
16
|
+
import resqpy.property as rqp
|
|
13
17
|
import pyetp.resqml_objects as ro
|
|
18
|
+
#import energyml.resqml.v2_0_1.resqmlv2 as ro
|
|
19
|
+
#import energyml.eml.v2_0.commonv2 as roc
|
|
14
20
|
from pyetp.config import SETTINGS
|
|
15
21
|
from pyetp.types import DataObject
|
|
16
22
|
|
|
@@ -21,8 +27,7 @@ if T.TYPE_CHECKING:
|
|
|
21
27
|
from xtgeo import RegularSurface
|
|
22
28
|
|
|
23
29
|
|
|
24
|
-
schema_version = "2.0"
|
|
25
|
-
|
|
30
|
+
schema_version = "2.0.1"
|
|
26
31
|
|
|
27
32
|
def get_data_object_type(obj: ro.AbstractObject):
|
|
28
33
|
return obj.__class__.__name__
|
|
@@ -83,8 +88,8 @@ def create_common_crs(title: str, projected_epsg, rotation: float = 0.0):
|
|
|
83
88
|
projected_uom=ro.LengthUom.M,
|
|
84
89
|
vertical_uom=ro.LengthUom.M,
|
|
85
90
|
zincreasing_downward=True,
|
|
86
|
-
vertical_crs=ro.
|
|
87
|
-
|
|
91
|
+
vertical_crs=ro.VerticalCrsEpsgCode(
|
|
92
|
+
epsg_code=projected_epsg
|
|
88
93
|
),
|
|
89
94
|
projected_crs=ro.ProjectedCrsEpsgCode(
|
|
90
95
|
epsg_code=projected_epsg,
|
|
@@ -139,7 +144,7 @@ def instantiate_resqml_grid(name: str, rotation: float, x0: float, y0: float, dx
|
|
|
139
144
|
fastest_axis_count=ny,
|
|
140
145
|
slowest_axis_count=nx,
|
|
141
146
|
geometry=ro.PointGeometry(
|
|
142
|
-
local_crs=ro.DataObjectReference(
|
|
147
|
+
local_crs= ro.DataObjectReference(
|
|
143
148
|
# NOTE: See Energistics Identifier Specification 4.0
|
|
144
149
|
# (it is downloaded alongside the RESQML v2.0.1
|
|
145
150
|
# standard) section 4.1 for an explanation on the
|
|
@@ -147,7 +152,8 @@ def instantiate_resqml_grid(name: str, rotation: float, x0: float, y0: float, dx
|
|
|
147
152
|
content_type=f"application/x-resqml+xml;version={schema_version};type={get_data_object_type(crs)}",
|
|
148
153
|
title=crs.citation.title,
|
|
149
154
|
uuid=crs.uuid,
|
|
150
|
-
)
|
|
155
|
+
)
|
|
156
|
+
,
|
|
151
157
|
points=ro.Point3dZValueArray(
|
|
152
158
|
supporting_geometry=ro.Point3dLatticeArray(
|
|
153
159
|
origin=ro.Point3d(
|
|
@@ -237,7 +243,7 @@ def uom_for_prop_title(pt: str):
|
|
|
237
243
|
return ro.ResqmlUom.VALUE
|
|
238
244
|
return ro.ResqmlUom.EUC
|
|
239
245
|
|
|
240
|
-
def create_resqml_property(prop_title, continuous, indexable_element, uns, epc, min_val=0.0, max_val=1.0,
|
|
246
|
+
def create_resqml_property(prop_title:str, continuous: bool, indexable_element: ro.IndexableElements, uns: ro.UnstructuredGridRepresentation, epc: ro.EpcExternalPartReference, min_val=0.0, max_val=1.0,
|
|
241
247
|
timeseries=None, time_index=-1, pre_existing_propertykind = None):
|
|
242
248
|
timeindex_ref = None
|
|
243
249
|
use_timeseries = timeseries is not None
|
|
@@ -253,7 +259,6 @@ def create_resqml_property(prop_title, continuous, indexable_element, uns, epc,
|
|
|
253
259
|
)
|
|
254
260
|
|
|
255
261
|
r_uom = ro.ResqmlUom( value= uom_for_prop_title(prop_title) )
|
|
256
|
-
# r_uom = ro.ResqmlUom( uom )
|
|
257
262
|
|
|
258
263
|
if (pre_existing_propertykind is None):
|
|
259
264
|
pk_uuid = uuid4()
|
|
@@ -357,8 +362,8 @@ def create_resqml_property(prop_title, continuous, indexable_element, uns, epc,
|
|
|
357
362
|
)
|
|
358
363
|
return cprop0, propertykind0
|
|
359
364
|
|
|
360
|
-
def create_resqml_mesh(rmdi, rmdts, geotimes, projected_epsg): #(rddms_mesh_data_initial, rddms_upload_data_timestep)
|
|
361
|
-
|
|
365
|
+
def create_resqml_mesh(rmdi, rmdts, geotimes, projected_epsg: int): #(rddms_mesh_data_initial, rddms_upload_data_timestep)
|
|
366
|
+
|
|
362
367
|
ro_timestamps = []
|
|
363
368
|
for i in geotimes:
|
|
364
369
|
ro_timestamps.append(
|
|
@@ -432,7 +437,7 @@ def create_resqml_mesh(rmdi, rmdts, geotimes, projected_epsg): #(rddms_mesh_dat
|
|
|
432
437
|
node_count=node_count,
|
|
433
438
|
face_count=face_count,
|
|
434
439
|
cell_shape=cellshape,
|
|
435
|
-
points=ro.
|
|
440
|
+
points=ro.Point3DHdf5Array(
|
|
436
441
|
coordinates=ro.Hdf5Dataset(
|
|
437
442
|
path_in_hdf_file=f"/RESQML/{str(hexa_uuid)}/points",
|
|
438
443
|
hdf_proxy=ro.DataObjectReference(
|
|
@@ -514,10 +519,8 @@ def create_resqml_mesh(rmdi, rmdts, geotimes, projected_epsg): #(rddms_mesh_dat
|
|
|
514
519
|
return uns, crs, epc, timeseries
|
|
515
520
|
|
|
516
521
|
|
|
517
|
-
def convert_epc_mesh_to_resqml_mesh(epc_filename, title_in, projected_epsg):
|
|
518
|
-
|
|
519
|
-
import resqpy.time_series as rts
|
|
520
|
-
import resqpy.unstructured as rug
|
|
522
|
+
def convert_epc_mesh_to_resqml_mesh(epc_filename: str, title_in: str, projected_epsg: int):
|
|
523
|
+
|
|
521
524
|
|
|
522
525
|
title = title_in or "hexamesh"
|
|
523
526
|
|
|
@@ -661,9 +664,8 @@ def convert_epc_mesh_to_resqml_mesh(epc_filename, title_in, projected_epsg):
|
|
|
661
664
|
return uns, crs, epc, timeseries, hexa
|
|
662
665
|
|
|
663
666
|
|
|
664
|
-
def convert_epc_mesh_property_to_resqml_mesh(epc_filename, hexa, prop_title, uns, epc, timeseries=None, time_indices: list[int] = []):
|
|
665
|
-
|
|
666
|
-
import resqpy.property as rqp
|
|
667
|
+
def convert_epc_mesh_property_to_resqml_mesh(epc_filename, hexa, prop_title, uns:ro.UnstructuredGridRepresentation, epc:ro.EpcExternalPartReference, timeseries=None, time_indices: list[int] = []):
|
|
668
|
+
|
|
667
669
|
|
|
668
670
|
model = rq.Model(epc_filename)
|
|
669
671
|
assert model is not None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "pyetp"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.34"
|
|
4
4
|
description = "Interface with OSDU RDDMS using ETP protocol"
|
|
5
5
|
authors = ["Adam Cheng <52572642+adamchengtkc@users.noreply.github.com>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -12,7 +12,7 @@ classifiers = [
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
[tool.poetry.dependencies]
|
|
15
|
-
python = ">=3.
|
|
15
|
+
python = ">=3.10, <3.13"
|
|
16
16
|
numpy = "^1.26.3"
|
|
17
17
|
websockets = "^12.0"
|
|
18
18
|
lxml = ">=4.9.4, <6.0"
|
|
@@ -20,12 +20,12 @@ pydantic = "^1.10"
|
|
|
20
20
|
redis = "^5.0.1"
|
|
21
21
|
async-lru = "^2.0.4"
|
|
22
22
|
async-timeout = { version = "^5.0", python = "<3.11" }
|
|
23
|
-
etpproto = "<1.0.7"
|
|
24
23
|
resqpy = ">4.16.0, <5.2"
|
|
25
24
|
|
|
26
25
|
pyarrow = "^15.0.0" # added to fix pandas deprecated warning in xtgeo
|
|
27
26
|
xtgeo = "^3.8.0"
|
|
28
27
|
xsdata = "^24.3.1"
|
|
28
|
+
etpproto = "^1.0.7"
|
|
29
29
|
|
|
30
30
|
[tool.poetry.group.dev.dependencies]
|
|
31
31
|
pytest = "^7.4.4"
|
pyetp-0.0.32/pyetp/types.py
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
from etptypes import ETPModel
|
|
3
|
-
from etptypes.energistics.etp.v12.datatypes.any_array import AnyArray
|
|
4
|
-
from etptypes.energistics.etp.v12.datatypes.any_array_type import AnyArrayType
|
|
5
|
-
from etptypes.energistics.etp.v12.datatypes.any_logical_array_type import \
|
|
6
|
-
AnyLogicalArrayType
|
|
7
|
-
from etptypes.energistics.etp.v12.datatypes.array_of_boolean import \
|
|
8
|
-
ArrayOfBoolean
|
|
9
|
-
from etptypes.energistics.etp.v12.datatypes.array_of_double import \
|
|
10
|
-
ArrayOfDouble
|
|
11
|
-
from etptypes.energistics.etp.v12.datatypes.array_of_float import ArrayOfFloat
|
|
12
|
-
from etptypes.energistics.etp.v12.datatypes.array_of_int import ArrayOfInt
|
|
13
|
-
from etptypes.energistics.etp.v12.datatypes.array_of_long import ArrayOfLong
|
|
14
|
-
from etptypes.energistics.etp.v12.datatypes.data_array_types.data_array import \
|
|
15
|
-
DataArray
|
|
16
|
-
from etptypes.energistics.etp.v12.datatypes.data_array_types.data_array_identifier import \
|
|
17
|
-
DataArrayIdentifier
|
|
18
|
-
from etptypes.energistics.etp.v12.datatypes.data_array_types.data_array_metadata import \
|
|
19
|
-
DataArrayMetadata
|
|
20
|
-
from etptypes.energistics.etp.v12.datatypes.data_value import DataValue
|
|
21
|
-
from etptypes.energistics.etp.v12.datatypes.error_info import ErrorInfo
|
|
22
|
-
from etptypes.energistics.etp.v12.datatypes.message_header import MessageHeader
|
|
23
|
-
from etptypes.energistics.etp.v12.datatypes.object.data_object import \
|
|
24
|
-
DataObject
|
|
25
|
-
from etptypes.energistics.etp.v12.datatypes.object.dataspace import Dataspace
|
|
26
|
-
from etptypes.energistics.etp.v12.datatypes.server_capabilities import \
|
|
27
|
-
ServerCapabilities
|
|
28
|
-
from etptypes.energistics.etp.v12.datatypes.supported_data_object import \
|
|
29
|
-
SupportedDataObject
|
|
30
|
-
from etptypes.energistics.etp.v12.datatypes.supported_protocol import \
|
|
31
|
-
SupportedProtocol
|
|
32
|
-
from etptypes.energistics.etp.v12.datatypes.version import Version
|
|
33
|
-
from etptypes.energistics.etp.v12.protocol.core.acknowledge import Acknowledge
|
|
34
|
-
from etptypes.energistics.etp.v12.protocol.core.authorize import Authorize
|
|
35
|
-
from etptypes.energistics.etp.v12.protocol.core.authorize_response import \
|
|
36
|
-
AuthorizeResponse
|
|
37
|
-
from etptypes.energistics.etp.v12.protocol.core.close_session import \
|
|
38
|
-
CloseSession
|
|
39
|
-
from etptypes.energistics.etp.v12.protocol.core.open_session import OpenSession
|
|
40
|
-
from etptypes.energistics.etp.v12.protocol.core.protocol_exception import \
|
|
41
|
-
ProtocolException
|
|
42
|
-
from etptypes.energistics.etp.v12.protocol.core.request_session import \
|
|
43
|
-
RequestSession
|
|
44
|
-
|
|
45
|
-
#
|
|
46
|
-
# NOTE we want to `from etptypes.energistics.etp.v12 import datatypes, protocol` and use this
|
|
47
|
-
# however this not supported with pylance as of yet, hence so many imports are reexported here
|
|
48
|
-
#
|
pyetp-0.0.32/pyetp/utils.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|