pyetp 0.0.39__py3-none-any.whl → 0.0.43__py3-none-any.whl

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/uri.py CHANGED
@@ -4,8 +4,8 @@ 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
- from pyetp.resqml_objects import AbstractObject
8
- #from energyml.eml.v2_0.commonv2 import AbstractObject
7
+
8
+ import resqml_objects.v201 as ro
9
9
 
10
10
 
11
11
  class _Mixin:
@@ -21,7 +21,10 @@ class _Mixin:
21
21
 
22
22
  @classmethod
23
23
  def __modify_schema__(cls, field_schema):
24
- field_schema.update(type="url", example="eml:///dataspace('my/space')/resqml20.ObjectName(5fe90ad4-6d34-4f73-a72d-992b26f8442e)")
24
+ field_schema.update(
25
+ type="url",
26
+ example="eml:///dataspace('my/space')/resqml20.ObjectName(5fe90ad4-6d34-4f73-a72d-992b26f8442e)",
27
+ )
25
28
 
26
29
  @classmethod
27
30
  def __get_validators__(cls):
@@ -38,7 +41,6 @@ class _Mixin:
38
41
 
39
42
 
40
43
  class DataspaceURI(_DataspaceURI, _Mixin):
41
-
42
44
  @classmethod
43
45
  def from_name(cls, name: str):
44
46
  return cls(f"eml:///dataspace('{name}')")
@@ -50,36 +52,46 @@ class DataspaceURI(_DataspaceURI, _Mixin):
50
52
  if isinstance(v, DataObjectURI):
51
53
  return cls.from_name(v.dataspace)
52
54
  if isinstance(v, str):
53
- if v.startswith('eml://'):
54
- return cls(v) if v.endswith('\')') else cls.from_name(DataObjectURI(v).dataspace)
55
+ if v.startswith("eml://"):
56
+ return (
57
+ cls(v)
58
+ if v.endswith("')")
59
+ else cls.from_name(DataObjectURI(v).dataspace)
60
+ )
55
61
  else:
56
62
  return cls.from_name(v)
57
63
  raise TypeError(f"Type {type(v)} not supported dataspace uri")
58
64
 
59
65
 
60
66
  class DataObjectURI(_DataObjectURI, _Mixin):
61
-
62
67
  @classmethod
63
- def from_parts(cls, duri:Union[DataspaceURI, str] , domain_and_version: str, obj_type: str, uuid:Union[ UUID ,str]):
68
+ def from_parts(
69
+ cls,
70
+ duri: Union[DataspaceURI, str],
71
+ domain_and_version: str,
72
+ obj_type: str,
73
+ uuid: Union[UUID, str],
74
+ ):
64
75
  duri = DataspaceURI.from_any(duri)
65
76
  return cls(f"{duri}/{domain_and_version}.{obj_type}({uuid})")
66
77
 
67
78
  @classmethod
68
- def from_obj(cls, dataspace: Union[DataspaceURI , str], obj: AbstractObject):
69
-
79
+ def from_obj(cls, dataspace: Union[DataspaceURI, str], obj: ro.AbstractObject):
70
80
  objname = obj.__class__.__name__
71
- if getattr(obj, 'Meta', None):
72
- namespace: str = getattr(obj.Meta, 'namespace', None) or getattr(obj.Meta, 'target_namespace')
81
+ if getattr(obj, "Meta", None):
82
+ namespace: str = getattr(obj.Meta, "namespace", None) or getattr(
83
+ obj.Meta, "target_namespace"
84
+ )
73
85
  namespace = namespace.lower()
74
86
  # TODO: we can rather look at citation.format - which could be used for xmlformat ? - however to be backward capatiable we check namespaces instead
75
- if namespace.endswith('resqmlv2'):
87
+ if namespace.endswith("resqmlv2"):
76
88
  domain = "resqml20"
77
- elif namespace.endswith('data/commonv2'):
89
+ elif namespace.endswith("data/commonv2"):
78
90
  domain = "eml20"
79
91
  else:
80
92
  raise TypeError(f"Could not parse domain from namespace ({namespace})")
81
93
  else:
82
- domain = "eml20" # fallback to eml20 for backwards compatibility.
94
+ domain = "eml20" # fallback to eml20 for backwards compatibility.
83
95
 
84
96
  return cls.from_parts(dataspace, domain, objname, obj.uuid)
85
97
 
@@ -87,5 +99,5 @@ class DataObjectURI(_DataObjectURI, _Mixin):
87
99
  BaseConfig.json_encoders = {
88
100
  DataspaceURI: lambda v: str(v),
89
101
  DataObjectURI: lambda v: str(v),
90
- **BaseConfig.json_encoders
102
+ **BaseConfig.json_encoders,
91
103
  }
pyetp/utils_arrays.py CHANGED
@@ -1,134 +1,260 @@
1
-
2
1
  import typing as T
3
2
 
4
3
  import numpy as np
5
- from scipy import interpolate
6
- from xtgeo import RegularSurface
4
+ import numpy.typing as npt
5
+ from etptypes.energistics.etp.v12.datatypes.any_array import AnyArray
6
+ from etptypes.energistics.etp.v12.datatypes.any_array_type import AnyArrayType
7
+ from etptypes.energistics.etp.v12.datatypes.any_logical_array_type import (
8
+ AnyLogicalArrayType,
9
+ )
10
+ from etptypes.energistics.etp.v12.datatypes.array_of_boolean import ArrayOfBoolean
11
+ from etptypes.energistics.etp.v12.datatypes.array_of_double import ArrayOfDouble
12
+ from etptypes.energistics.etp.v12.datatypes.array_of_float import ArrayOfFloat
13
+ from etptypes.energistics.etp.v12.datatypes.array_of_int import ArrayOfInt
14
+ from etptypes.energistics.etp.v12.datatypes.array_of_long import ArrayOfLong
15
+ from etptypes.energistics.etp.v12.datatypes.data_array_types.data_array import (
16
+ DataArray,
17
+ )
18
+ from etptypes.energistics.etp.v12.datatypes.data_array_types.data_array_metadata import (
19
+ DataArrayMetadata,
20
+ )
21
+
22
+ SUPPORTED_ARRAY_TYPES: T.TypeAlias = (
23
+ ArrayOfFloat | ArrayOfBoolean | ArrayOfInt | ArrayOfLong | ArrayOfDouble
24
+ )
25
+
26
+
27
+ # See section 13.2.2.1 for the allowed mapping between logical array types and
28
+ # transport array types.
29
+ # NOTE: Currently the logical-array-mapping does not work on the
30
+ # open-etp-server. We write the relevant logical array type, but we only get
31
+ # AnyLogicalArrayType.ARRAY_OF_BOOLEAN in return from the server.
32
+ _ANY_LOGICAL_ARRAY_TYPE_MAP: dict[npt.DTypeLike, AnyLogicalArrayType] = {
33
+ np.dtype(np.bool_): AnyLogicalArrayType.ARRAY_OF_BOOLEAN,
34
+ np.dtype(np.int8): AnyLogicalArrayType.ARRAY_OF_INT8,
35
+ np.dtype(np.uint8): AnyLogicalArrayType.ARRAY_OF_UINT8,
36
+ np.dtype("<i2"): AnyLogicalArrayType.ARRAY_OF_INT16_LE,
37
+ np.dtype("<i4"): AnyLogicalArrayType.ARRAY_OF_INT32_LE,
38
+ np.dtype("<i8"): AnyLogicalArrayType.ARRAY_OF_INT64_LE,
39
+ np.dtype("<u2"): AnyLogicalArrayType.ARRAY_OF_UINT16_LE,
40
+ np.dtype("<u4"): AnyLogicalArrayType.ARRAY_OF_UINT32_LE,
41
+ np.dtype("<u8"): AnyLogicalArrayType.ARRAY_OF_UINT64_LE,
42
+ np.dtype("<f4"): AnyLogicalArrayType.ARRAY_OF_FLOAT32_LE,
43
+ np.dtype("<f8"): AnyLogicalArrayType.ARRAY_OF_DOUBLE64_LE,
44
+ np.dtype(">i2"): AnyLogicalArrayType.ARRAY_OF_INT16_BE,
45
+ np.dtype(">i4"): AnyLogicalArrayType.ARRAY_OF_INT32_BE,
46
+ np.dtype(">i8"): AnyLogicalArrayType.ARRAY_OF_INT64_BE,
47
+ np.dtype(">u2"): AnyLogicalArrayType.ARRAY_OF_UINT16_BE,
48
+ np.dtype(">u4"): AnyLogicalArrayType.ARRAY_OF_UINT32_BE,
49
+ np.dtype(">u8"): AnyLogicalArrayType.ARRAY_OF_UINT64_BE,
50
+ np.dtype(">f4"): AnyLogicalArrayType.ARRAY_OF_FLOAT32_BE,
51
+ np.dtype(">f8"): AnyLogicalArrayType.ARRAY_OF_DOUBLE64_BE,
52
+ }
7
53
 
8
- from pyetp.types import (AnyArray, AnyArrayType, ArrayOfBoolean, ArrayOfDouble,
9
- ArrayOfFloat, ArrayOfInt, ArrayOfLong, DataArray,
10
- DataArrayMetadata)
54
+ _INV_ANY_LOGICAL_ARRAY_TYPE_MAP: dict[AnyLogicalArrayType, npt.DTypeLike] = {
55
+ v: k for k, v in _ANY_LOGICAL_ARRAY_TYPE_MAP.items()
56
+ }
11
57
 
12
- SUPPORED_ARRAY_TYPES = T.Union[ArrayOfFloat, ArrayOfBoolean, ArrayOfInt, ArrayOfLong, ArrayOfDouble]
13
58
 
14
- _ARRAY_MAP_TYPES: dict[AnyArrayType, np.dtype[T.Any]] = {
15
- AnyArrayType.ARRAY_OF_FLOAT: np.dtype(np.float32),
16
- AnyArrayType.ARRAY_OF_DOUBLE: np.dtype(np.float64),
17
- AnyArrayType.ARRAY_OF_INT: np.dtype(np.int32),
18
- AnyArrayType.ARRAY_OF_LONG: np.dtype(np.int64),
19
- AnyArrayType.ARRAY_OF_BOOLEAN: np.dtype(np.bool_)
59
+ # TODO: This map should be used once the logical-array-type is supported in the
60
+ # open-etp-server.
61
+ # _ANY_ARRAY_TYPE_MAP: dict[npt.DTypeLike, AnyArrayType] = {
62
+ # np.dtype(np.bool_): AnyArrayType.ARRAY_OF_BOOLEAN,
63
+ # np.dtype(np.int8): AnyArrayType.BYTES,
64
+ # np.dtype(np.uint8): AnyArrayType.BYTES,
65
+ # np.dtype("<i2"): AnyArrayType.BYTES,
66
+ # np.dtype("<i4"): AnyArrayType.BYTES,
67
+ # np.dtype("<i8"): AnyArrayType.BYTES,
68
+ # np.dtype("<u2"): AnyArrayType.BYTES,
69
+ # np.dtype("<u4"): AnyArrayType.BYTES,
70
+ # np.dtype("<u8"): AnyArrayType.BYTES,
71
+ # np.dtype("<f4"): AnyArrayType.ARRAY_OF_FLOAT,
72
+ # np.dtype("<f8"): AnyArrayType.ARRAY_OF_DOUBLE,
73
+ # np.dtype(">i2"): AnyArrayType.BYTES,
74
+ # np.dtype(">i4"): AnyArrayType.BYTES,
75
+ # np.dtype(">i8"): AnyArrayType.BYTES,
76
+ # np.dtype(">u2"): AnyArrayType.BYTES,
77
+ # np.dtype(">u4"): AnyArrayType.BYTES,
78
+ # np.dtype(">u8"): AnyArrayType.BYTES,
79
+ # np.dtype(">f4"): AnyArrayType.BYTES,
80
+ # np.dtype(">f8"): AnyArrayType.BYTES,
81
+ # }
82
+
83
+
84
+ # This AnyArrayType-map is used until the logical-array-type is properly
85
+ # implemented for the open-etp-server. In this case we
86
+ _ANY_ARRAY_TYPE_MAP: dict[npt.DTypeLike, AnyArrayType] = {
87
+ np.dtype(np.bool_): AnyArrayType.ARRAY_OF_BOOLEAN,
88
+ np.dtype(np.int8): AnyArrayType.BYTES,
89
+ np.dtype("<i4"): AnyArrayType.ARRAY_OF_INT,
90
+ np.dtype("<i8"): AnyArrayType.ARRAY_OF_LONG,
91
+ np.dtype("<f4"): AnyArrayType.ARRAY_OF_FLOAT,
92
+ np.dtype("<f8"): AnyArrayType.ARRAY_OF_DOUBLE,
93
+ }
94
+ valid_dtypes = list(_ANY_ARRAY_TYPE_MAP)
95
+
96
+ _INV_ANY_ARRAY_TYPE_MAP: dict[AnyArrayType, npt.DTypeLike] = {
97
+ AnyArrayType.ARRAY_OF_BOOLEAN: np.dtype(np.bool_),
98
+ # The BYTES-arrays are converted to the proper dtype using the logical
99
+ # array type. We can therefore interpret the bytes as np.int8, before we
100
+ # combine the byte strings to the proper type.
101
+ AnyArrayType.BYTES: np.dtype(np.int8),
102
+ AnyArrayType.ARRAY_OF_INT: np.dtype("<i4"),
103
+ AnyArrayType.ARRAY_OF_LONG: np.dtype("<i8"),
104
+ AnyArrayType.ARRAY_OF_FLOAT: np.dtype("<f4"),
105
+ AnyArrayType.ARRAY_OF_DOUBLE: np.dtype("<f8"),
20
106
  }
21
107
 
22
- _ARRAY_MAP: dict[AnyArrayType, T.Type[SUPPORED_ARRAY_TYPES]] = {
108
+
109
+ _ANY_ARRAY_MAP: dict[AnyArrayType, SUPPORTED_ARRAY_TYPES] = {
23
110
  AnyArrayType.ARRAY_OF_FLOAT: ArrayOfFloat,
24
111
  AnyArrayType.ARRAY_OF_DOUBLE: ArrayOfDouble,
25
112
  AnyArrayType.ARRAY_OF_INT: ArrayOfInt,
26
113
  AnyArrayType.ARRAY_OF_LONG: ArrayOfLong,
27
- AnyArrayType.ARRAY_OF_BOOLEAN: ArrayOfBoolean
114
+ AnyArrayType.ARRAY_OF_BOOLEAN: ArrayOfBoolean,
115
+ AnyArrayType.BYTES: bytes,
28
116
  }
29
117
 
30
-
31
- def get_transport_from_name(k: str):
32
- return AnyArrayType(k[0].lower() + k[1:])
118
+ _INV_ANY_ARRAY_MAP: dict[SUPPORTED_ARRAY_TYPES, AnyArrayType] = {
119
+ v: k for k, v in _ANY_ARRAY_MAP.items()
120
+ }
33
121
 
34
122
 
35
- def get_transport(dtype: np.dtype):
123
+ def check_if_array_is_valid_dtype(array: npt.NDArray[T.Any]) -> bool:
124
+ return array.dtype in valid_dtypes
36
125
 
37
- arraytype = [item[0] for item in _ARRAY_MAP_TYPES.items() if item[1] == dtype]
38
- if not len(arraytype):
39
- raise TypeError(f"Not {type(dtype)} supported")
40
126
 
41
- return arraytype[0]
127
+ def get_valid_dtype_cast(array: npt.NDArray[T.Any]) -> npt.DTypeLike:
128
+ if check_if_array_is_valid_dtype(array):
129
+ return array.dtype
42
130
 
131
+ if array.dtype == np.dtype(np.uint8):
132
+ return np.dtype(np.int8)
133
+ elif array.dtype == np.dtype("<u2"):
134
+ return np.dtype("<i2")
135
+ elif array.dtype == np.dtype(">u2"):
136
+ return np.dtype("<i2")
137
+ elif array.dtype == np.dtype("<u4"):
138
+ return np.dtype("<i4")
139
+ elif array.dtype == np.dtype(">u4"):
140
+ return np.dtype("<i4")
141
+ elif array.dtype == np.dtype("<u8"):
142
+ return np.dtype("<i8")
143
+ elif array.dtype == np.dtype(">u8"):
144
+ return np.dtype("<i8")
43
145
 
44
- def get_cls(dtype: np.dtype):
45
- return _ARRAY_MAP[get_transport(dtype)]
146
+ raise TypeError(f"Dtype {array.dtype} does not have a valid cast")
46
147
 
47
148
 
48
- def get_dtype(item: T.Union[AnyArray, AnyArrayType]):
49
- atype = item if isinstance(item, AnyArrayType) else get_transport_from_name(item.item.__class__.__name__)
149
+ def get_logical_array_type(dtype: npt.DTypeLike) -> AnyLogicalArrayType:
150
+ logical_array_type = _ANY_LOGICAL_ARRAY_TYPE_MAP.get(dtype)
50
151
 
51
- if atype not in _ARRAY_MAP_TYPES:
52
- raise TypeError(f"Not {atype} supported")
152
+ if logical_array_type is not None:
153
+ return logical_array_type
53
154
 
54
- return _ARRAY_MAP_TYPES[atype]
155
+ # Here we might be taking a chance by not caring about the endianess of the
156
+ # string.
157
+ if dtype.type == np.str_:
158
+ return AnyLogicalArrayType.ARRAY_OF_STRING
55
159
 
160
+ # We ignore the AnyLogicalArrayType.ARRAY_OF_CUSTOM for now.
161
+ raise KeyError(f"Data type {dtype} is not a valid ETP v1.2 logical array type")
56
162
 
57
- def get_nbytes(md: DataArrayMetadata):
58
- dtype = get_dtype(md.transport_array_type)
59
- return int(np.prod(np.array(md.dimensions)) * dtype.itemsize)
60
163
 
164
+ def get_transport_array_type(dtype: npt.DTypeLike) -> AnyArrayType:
165
+ transport_array_type = _ANY_ARRAY_TYPE_MAP.get(dtype)
61
166
 
62
- def to_numpy(data_array: DataArray):
63
- dims: T.Tuple[int, ...] = tuple(map(int, data_array.dimensions))
64
- return np.asarray(
65
- data_array.data.item.values, # type: ignore
66
- dtype=get_dtype(data_array.data)
67
- ).reshape(dims)
167
+ if transport_array_type is not None:
168
+ return transport_array_type
68
169
 
170
+ # Here we might be taking a chance by not caring about the endianess of the
171
+ # string.
172
+ if dtype.type == np.str_:
173
+ return AnyArrayType.ARRAY_OF_STRING
69
174
 
70
- def to_data_array(data: np.ndarray):
71
- cls = get_cls(data.dtype)
72
- return DataArray(
73
- dimensions=data.shape, # type: ignore
74
- data=AnyArray(item=cls(values=data.flatten().tolist()))
175
+ raise KeyError(
176
+ f"Data type {dtype} does not have a valid map to an ETP v1.2 transport array "
177
+ f"type. Valid types are: {list(_ANY_ARRAY_TYPE_MAP)}"
75
178
  )
76
179
 
77
180
 
78
- def mid_point_rectangle(arr: np.ndarray):
79
- all_x = arr[:, 0]
80
- all_y = arr[:, 1]
81
- min_x = np.min(all_x)
82
- min_y = np.min(all_y)
83
- mid_x = ((np.max(all_x)-min_x)/2)+min_x
84
- mid_y = ((np.max(all_y)-min_y)/2)+min_y
85
- return np.array([mid_x, mid_y])
86
-
87
-
88
- def grid_xtgeo(data: np.ndarray):
89
- max_x = np.nanmax(data[:, 0])
90
- max_y = np.nanmax(data[:, 1])
91
- min_x = np.nanmin(data[:, 0])
92
- min_y = np.nanmin(data[:, 1])
93
- u_x = np.sort(np.unique(data[:, 0]))
94
- u_y = np.sort(np.unique(data[:, 1]))
95
- xinc = u_x[1] - u_x[0]
96
- yinc = u_y[1] - u_y[0]
97
- grid_x, grid_y = np.mgrid[
98
- min_x: max_x + xinc: xinc,
99
- min_y: max_y + yinc: yinc,
100
- ]
101
-
102
- interp = interpolate.LinearNDInterpolator(data[:, :-1], data[:, -1], fill_value=np.nan, rescale=False)
103
- z = interp(np.array([grid_x.flatten(), grid_y.flatten()]).T)
104
- zz = np.reshape(z, grid_x.shape)
105
-
106
- return RegularSurface(
107
- ncol=grid_x.shape[0],
108
- nrow=grid_x.shape[1],
109
- xori=min_x,
110
- yori=min_y,
111
- xinc=xinc,
112
- yinc=yinc,
113
- rotation=0.0,
114
- values=zz,
181
+ def get_logical_and_transport_array_types(
182
+ dtype: npt.DTypeLike,
183
+ ) -> tuple[AnyLogicalArrayType, AnyArrayType]:
184
+ # See section 13.2.2.1 in the ETP v1.2 specification for the allowed
185
+ # mappings between the logical and transport types.
186
+ # Using this function ensures that the combination of the logical and
187
+ # transport array types are valid (it is set up in valid combinations in
188
+ # the mapping dictionaries at the top).
189
+
190
+ return get_logical_array_type(dtype), get_transport_array_type(dtype)
191
+
192
+
193
+ def get_etp_data_array_from_numpy(data: npt.NDArray) -> DataArray:
194
+ transport_array_type = get_transport_array_type(data.dtype)
195
+ cls = _ANY_ARRAY_MAP[transport_array_type]
196
+
197
+ if cls is bytes:
198
+ # In the current implementation we only support 1-byte sized dtype's
199
+ # when using "bytes". In the future, with logical array types, this can
200
+ # cover multiple dtypes, but then the dimensions must be adjusted.
201
+ itemsize = data.dtype.itemsize
202
+ item = np.ravel(data).tobytes()
203
+ dimensions = list(data.shape)
204
+ dimensions[-1] = dimensions[-1] * itemsize
205
+
206
+ return DataArray(dimensions=dimensions, data=AnyArray(item=item))
207
+
208
+ return DataArray(
209
+ dimensions=data.shape, data=AnyArray(item=cls(values=np.ravel(data).tolist()))
115
210
  )
116
211
 
117
212
 
118
- def get_cells_positions(points: np.ndarray, n_cells: int, n_cell_per_pos: int, layers_per_sediment_unit: int, n_node_per_pos: int, node_index: int):
119
- results = np.zeros((int(n_cells/n_cell_per_pos), 3), dtype=np.float64)
120
- grid_x_pos = np.unique(points[:, 0])
121
- grid_y_pos = np.unique(points[:, 1])
122
- counter = 0
123
- # find cell index and location
124
-
125
- for y_ind in range(0, len(grid_y_pos)-1):
126
- for x_ind in range(0, len(grid_x_pos)-1):
127
- top_depth = []
128
- for corner_x in range(layers_per_sediment_unit):
129
- for corner_y in range(layers_per_sediment_unit):
130
- node_indx = (((y_ind+corner_y)*len(grid_x_pos) + (x_ind+corner_x)) * n_node_per_pos) + node_index
131
- top_depth.append(points[node_indx])
132
- results[counter, 0:2] = mid_point_rectangle(np.array(top_depth))
133
- counter += 1
134
- return results
213
+ def get_transport_array_size(metadata: DataArrayMetadata) -> int:
214
+ dtype = _INV_ANY_ARRAY_TYPE_MAP[metadata.transport_array_type]
215
+ return int(np.prod(metadata.dimensions) * dtype.itemsize)
216
+
217
+
218
+ def get_dtype_from_any_array_class(cls: AnyArray) -> npt.DTypeLike:
219
+ if cls is bytes:
220
+ return np.dtype(np.int8)
221
+ elif cls is ArrayOfBoolean:
222
+ return np.dtype(np.bool_)
223
+ elif cls is ArrayOfInt:
224
+ return np.dtype("<i4")
225
+ elif cls is ArrayOfLong:
226
+ return np.dtype("<i8")
227
+ elif cls is ArrayOfFloat:
228
+ return np.dtype("<f4")
229
+ elif cls is ArrayOfDouble:
230
+ return np.dtype("<f8")
231
+ # TODO: Update NumPy to >= 2.0, and import the ArrayOfString-class
232
+ # elif cls == ArrayOfString:
233
+ # return np.StringDType()
234
+
235
+ raise TypeError(f"Class {cls} is not a valid array class")
236
+
237
+
238
+ def get_dtype_from_any_array_type(_type: T.Union[AnyArrayType | str]) -> npt.DTypeLike:
239
+ enum_name = AnyArrayType(_type)
240
+ return _INV_ANY_ARRAY_TYPE_MAP[enum_name]
241
+
242
+
243
+ def get_numpy_array_from_etp_data_array(
244
+ data_array: DataArray,
245
+ ) -> npt.NDArray[
246
+ # The types used here do not tell which endianess is used for the returned
247
+ # arrays, but until we can use np.dtype("<f4")-like syntax (Python > 3.10),
248
+ # this will do.
249
+ np.int8 | np.bool_ | np.int32 | np.int64 | np.float32 | np.float64
250
+ ]:
251
+ dtype = get_dtype_from_any_array_class(type(data_array.data.item))
252
+
253
+ if type(data_array.data.item) is bytes:
254
+ return np.array(np.frombuffer(data_array.data.item, dtype=dtype)).reshape(
255
+ data_array.dimensions
256
+ )
257
+
258
+ return np.array(data_array.data.item.values, dtype=dtype).reshape(
259
+ data_array.dimensions
260
+ )