forked from equinor/webviz
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support sending of binary arrays using base64 encoding (equinor#371)
- Loading branch information
Showing
21 changed files
with
333 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,94 @@ | ||
import base64 | ||
from typing import Any, Optional | ||
from typing import Literal | ||
from pydantic import BaseModel | ||
|
||
import numpy as np | ||
from numpy.typing import NDArray | ||
|
||
|
||
def b64_encode_numpy(obj: Any) -> dict: | ||
# Convert 1D numpy arrays with numeric types to memoryviews with | ||
# datatype and shape metadata. | ||
if len(obj) == 0: | ||
return obj.tolist() | ||
|
||
buffer: Optional[str] = None | ||
dtype = obj.dtype | ||
if dtype.kind in ["u", "i", "f"] and str(dtype) != "int64" and str(dtype) != "uint64": | ||
# We have a numpy array that is compatible with JavaScript typed | ||
# arrays | ||
buffer = base64.b64encode(memoryview(obj.ravel(order="C"))).decode("utf-8") | ||
return {"bvals": buffer, "dtype": str(dtype), "shape": obj.shape} | ||
|
||
dtype_str: Optional[str] = None | ||
# Try to see if we can downsize the array | ||
max_value = np.amax(obj) | ||
min_value = np.amin(obj) | ||
signed = min_value < 0 | ||
test_value = max(max_value, -min_value) | ||
if test_value < np.iinfo(np.int16).max and signed: | ||
dtype_str = "int16" | ||
buffer = base64.b64encode(memoryview(obj.astype(np.int16).ravel(order="C"))).decode("utf-8") | ||
elif test_value < np.iinfo(np.int32).max and signed: | ||
dtype_str = "int32" | ||
buffer = base64.b64encode(memoryview(obj.astype(np.int32).ravel(order="C"))).decode("utf-8") | ||
elif test_value < np.iinfo(np.uint16).max and not signed: | ||
dtype_str = "uint16" | ||
buffer = base64.b64encode(memoryview(obj.astype(np.uint16).ravel(order="C"))).decode("utf-8") | ||
elif test_value < np.iinfo(np.uint32).max and not signed: | ||
dtype_str = "uint32" | ||
buffer = base64.b64encode(memoryview(obj.astype(np.uint32).ravel(order="C"))).decode("utf-8") | ||
|
||
if dtype: | ||
return {"bvals": buffer, "dtype": dtype_str, "shape": obj.shape} | ||
|
||
# Convert all other numpy arrays to lists | ||
return obj.tolist() | ||
class B64FloatArray(BaseModel): | ||
element_type: Literal["float32", "float64"] | ||
data_b64str: str | ||
|
||
|
||
class B64UintArray(BaseModel): | ||
element_type: Literal["uint16", "uint32", "uint64"] | ||
data_b64str: str | ||
|
||
|
||
class B64IntArray(BaseModel): | ||
element_type: Literal["int16", "int32"] | ||
data_b64str: str | ||
|
||
|
||
# class B64TypedArray(BaseModel): | ||
# element_type: Literal["float32", "float64", "uint16", "uint32", "uint64", "int16", "int32"] | ||
# data_b64str: str | ||
|
||
|
||
def b64_encode_float_array_as_float32(input_arr: NDArray[np.floating] | list[float]) -> B64FloatArray: | ||
""" | ||
Base64 encodes an array of floating point numbers using 32bit float element size. | ||
""" | ||
np_arr: NDArray[np.float32] = np.asarray(input_arr, dtype=np.float32) | ||
base64_str = _base64_encode_numpy_arr_to_str(np_arr) | ||
return B64FloatArray(element_type="float32", data_b64str=base64_str) | ||
|
||
|
||
def b64_encode_float_array_as_float64(input_arr: NDArray[np.floating] | list[float]) -> B64FloatArray: | ||
""" | ||
Base64 encodes array of floating point numbers using 64bit float element size. | ||
""" | ||
np_arr: NDArray[np.float64] = np.asarray(input_arr, dtype=np.float64) | ||
base64_str = _base64_encode_numpy_arr_to_str(np_arr) | ||
return B64FloatArray(element_type="float64", data_b64str=base64_str) | ||
|
||
|
||
def b64_encode_int_array_as_int32(input_arr: NDArray[np.integer] | list[int]) -> B64IntArray: | ||
""" | ||
Base64 encodes an array of signed integers as using 32bit int element size. | ||
""" | ||
np_arr: NDArray[np.int32] = np.asarray(input_arr, dtype=np.int32) | ||
base64_str = _base64_encode_numpy_arr_to_str(np_arr) | ||
return B64IntArray(element_type="int32", data_b64str=base64_str) | ||
|
||
|
||
def b64_encode_uint_array_as_uint32(input_arr: NDArray[np.unsignedinteger] | list[int]) -> B64UintArray: | ||
""" | ||
Base64 encodes an array of unsigned integers using 32bit uint element size. | ||
""" | ||
np_arr: NDArray[np.uint32] = np.asarray(input_arr, dtype=np.uint32) | ||
base64_str = _base64_encode_numpy_arr_to_str(np_arr) | ||
return B64UintArray(element_type="uint32", data_b64str=base64_str) | ||
|
||
|
||
def b64_encode_uint_array_as_smallest_size( | ||
input_arr: NDArray[np.unsignedinteger] | list[int], max_value: int | None = None | ||
) -> B64UintArray: | ||
""" | ||
Base64 encodes an array of unsigned integers using the smallest possible element size. | ||
If the maximum value in the array is known, it can be specified in the max_value parameter. | ||
""" | ||
if max_value is None: | ||
max_value = np.amax(input_arr) | ||
|
||
element_type: Literal["uint16", "uint32", "uint64"] | ||
|
||
if max_value <= np.iinfo(np.uint16).max: | ||
np_arr = np.asarray(input_arr, dtype=np.uint16) | ||
element_type = "uint16" | ||
elif max_value <= np.iinfo(np.uint32).max: | ||
np_arr = np.asarray(input_arr, dtype=np.uint32) | ||
element_type = "uint32" | ||
else: | ||
np_arr = np.asarray(input_arr, dtype=np.uint64) | ||
element_type = "uint64" | ||
|
||
base64_str = _base64_encode_numpy_arr_to_str(np_arr) | ||
|
||
return B64UintArray(element_type=element_type, data_b64str=base64_str) | ||
|
||
|
||
def _base64_encode_numpy_arr_to_str(np_arr: NDArray) -> str: | ||
base64_bytes: bytes = base64.b64encode(np_arr.ravel(order="C").data) | ||
return base64_bytes.decode("ascii") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,15 @@ | ||
from typing import List | ||
|
||
import numpy as np | ||
from numpy.typing import NDArray | ||
import xtgeo | ||
|
||
|
||
def surface_to_float32_array(surface: xtgeo.RegularSurface) -> List[float]: | ||
values = surface.values.astype(np.float32) | ||
values.fill_value = np.nan | ||
values = np.ma.filled(values) | ||
def surface_to_float32_numpy_array(surface: xtgeo.RegularSurface) -> NDArray[np.float32]: | ||
masked_values = surface.values.astype(np.float32) | ||
values = np.ma.filled(masked_values, fill_value=np.nan) | ||
|
||
# Rotate 90 deg left. | ||
# This will cause the width of to run along the X axis | ||
# and height of along Y axis (starting from bottom.) | ||
values = np.rot90(values) | ||
|
||
return values.flatten().tolist() | ||
return values.flatten() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* istanbul ignore file */ | ||
/* tslint:disable */ | ||
/* eslint-disable */ | ||
|
||
export type B64FloatArray = { | ||
element_type: B64FloatArray.element_type; | ||
data_b64str: string; | ||
}; | ||
|
||
export namespace B64FloatArray { | ||
|
||
export enum element_type { | ||
FLOAT32 = 'float32', | ||
FLOAT64 = 'float64', | ||
} | ||
|
||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* istanbul ignore file */ | ||
/* tslint:disable */ | ||
/* eslint-disable */ | ||
|
||
export type B64UintArray = { | ||
element_type: B64UintArray.element_type; | ||
data_b64str: string; | ||
}; | ||
|
||
export namespace B64UintArray { | ||
|
||
export enum element_type { | ||
UINT16 = 'uint16', | ||
UINT32 = 'uint32', | ||
UINT64 = 'uint64', | ||
} | ||
|
||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.