Skip to content

Commit 86a6c55

Browse files
committed
pass numpy conversions as typed array spec
1 parent 277f1bb commit 86a6c55

File tree

1 file changed

+78
-1
lines changed

1 file changed

+78
-1
lines changed

packages/python/plotly/_plotly_utils/basevalidators.py

+78-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,83 @@ def to_scalar_or_list(v):
5050
return v
5151

5252

53+
plotlyjsShortTypes = {
54+
"int8": "i1",
55+
"uint8": "u1",
56+
"int16": "i2",
57+
"uint16": "u2",
58+
"int32": "i4",
59+
"uint32": "u4",
60+
"float32": "f4",
61+
"float64": "f8",
62+
}
63+
64+
int8min = -128
65+
int8max = 127
66+
int16min = -32768
67+
int16max = 32767
68+
int32min = -2147483648
69+
int32max = 2147483647
70+
71+
uint8max = 255
72+
uint16max = 65535
73+
uint32max = 4294967295
74+
75+
76+
def to_typed_array_spec(v):
77+
"""
78+
Convert numpy array to plotly.js typed array sepc
79+
If not possible return the original value
80+
"""
81+
v = copy_to_readonly_numpy_array(v)
82+
83+
np = get_module("numpy", should_load=False)
84+
if not isinstance(v, np.ndarray):
85+
return v
86+
87+
dtype = str(v.dtype)
88+
89+
# convert default Big Ints until we could support them in plotly.js
90+
if dtype == "int64":
91+
max = v.max()
92+
min = v.min()
93+
if max <= int8max and min >= int8min:
94+
v = v.astype("int8")
95+
elif max <= int16max and min >= int16min:
96+
v = v.astype("int16")
97+
elif max <= int32max and min >= int32min:
98+
v = v.astype("int32")
99+
else:
100+
return v
101+
102+
elif dtype == "uint64":
103+
max = v.max()
104+
min = v.min()
105+
if max <= uint8max and min >= 0:
106+
v = v.astype("uint8")
107+
elif max <= uint16max and min >= 0:
108+
v = v.astype("uint16")
109+
elif max <= uint32max and min >= 0:
110+
v = v.astype("uint32")
111+
else:
112+
return v
113+
114+
dtype = str(v.dtype)
115+
116+
if dtype in plotlyjsShortTypes:
117+
arrObj = {
118+
"dtype": plotlyjsShortTypes[dtype],
119+
"bdata": base64.b64encode(v).decode("ascii"),
120+
}
121+
122+
if v.ndim > 1:
123+
arrObj["shape"] = str(v.shape)[1:-1]
124+
125+
return arrObj
126+
127+
return v
128+
129+
53130
def copy_to_readonly_numpy_array(v, kind=None, force_numeric=False):
54131
"""
55132
Convert an array-like value into a read-only numpy array
@@ -415,7 +492,7 @@ def validate_coerce(self, v):
415492
# Pass typed array spec through
416493
pass
417494
elif is_homogeneous_array(v):
418-
v = copy_to_readonly_numpy_array(v)
495+
v = to_typed_array_spec(v)
419496
elif is_simple_array(v):
420497
v = to_scalar_or_list(v)
421498
else:

0 commit comments

Comments
 (0)