|
18 | 18 | from uuid import uuid4 |
19 | 19 | from collections import namedtuple |
20 | 20 |
|
| 21 | +import orjson |
21 | 22 | import dash |
22 | 23 | import numpy as np |
23 | 24 | import pandas as pd |
@@ -291,7 +292,7 @@ def _check_update_trace_data( |
291 | 292 | s_res: pd.Series = downsampler.aggregate( |
292 | 293 | hf_series, hf_trace_data["max_n_samples"] |
293 | 294 | ) |
294 | | - trace["x"] = s_res.index |
| 295 | + trace["x"] = self._parse_dtype_orjson(s_res.index) |
295 | 296 | trace["y"] = s_res.values |
296 | 297 | # todo -> first draft & not MP safe |
297 | 298 |
|
@@ -700,9 +701,14 @@ def _parse_get_trace_props( |
700 | 701 | except ValueError: |
701 | 702 | hf_y = hf_y.astype("str") |
702 | 703 |
|
703 | | - # orjson encoding doesn't like to encode with uint8 & uint16 dtype |
704 | | - if str(hf_y.dtype) in ["uint8", "uint16"]: |
705 | | - hf_y = hf_y.astype("uint32") |
| 704 | + msg = ( |
| 705 | + "Plotly-Resampler its aggregator functions do not support the float128" |
| 706 | + + " dtype, so please consider casting your data to float64\n." |
| 707 | + + " If you have an eligible usecase where float128 still is necessary," |
| 708 | + + " please consider making an issue on GitHub." |
| 709 | + ) |
| 710 | + assert hf_x.dtype != np.float128, msg |
| 711 | + assert hf_y.dtype != np.float128, msg |
706 | 712 |
|
707 | 713 | assert len(hf_x) == len(hf_y), "x and y have different length!" |
708 | 714 | else: |
@@ -1152,8 +1158,7 @@ def replace(self, figure: go.Figure, convert_existing_traces: bool = True): |
1152 | 1158 | ) |
1153 | 1159 |
|
1154 | 1160 | def construct_update_data( |
1155 | | - self, |
1156 | | - relayout_data: dict |
| 1161 | + self, relayout_data: dict |
1157 | 1162 | ) -> Union[List[dict], dash.no_update]: |
1158 | 1163 | """Construct the to-be-updated front-end data, based on the layout change. |
1159 | 1164 |
|
@@ -1261,6 +1266,24 @@ def construct_update_data( |
1261 | 1266 | layout_traces_list.append(trace_reduced) |
1262 | 1267 | return layout_traces_list |
1263 | 1268 |
|
| 1269 | + @staticmethod |
| 1270 | + def _parse_dtype_orjson(series: np.ndarray) -> np.ndarray: |
| 1271 | + """Verify the orjson compatibility of the series and convert it if needed.""" |
| 1272 | + # NOTE: |
| 1273 | + # * float16 and float128 aren't supported with latest orjson versions (3.8.1) |
| 1274 | + # * this method assumes that the it will not get a float128 series |
| 1275 | + if series.dtype in [np.float16]: |
| 1276 | + return series.astype(np.float32) |
| 1277 | + |
| 1278 | + # orjson < 3.8.0 encoding cannot encode with int16 & uint16 dtype |
| 1279 | + elif series.dtype in [np.int16, np.uint16]: |
| 1280 | + major_v, minor_v = list(map(int, orjson.__version__.split(".")))[:2] |
| 1281 | + if major_v < 3 or major_v == 3 and minor_v < 8: |
| 1282 | + if series.dtype == np.uint16: |
| 1283 | + return series.astype("uint32") |
| 1284 | + return series.astype(np.int32) |
| 1285 | + return series |
| 1286 | + |
1264 | 1287 | @staticmethod |
1265 | 1288 | def _re_matches(regex: re.Pattern, strings: Iterable[str]) -> List[str]: |
1266 | 1289 | """Returns all the items in ``strings`` which regex.match(es) ``regex``.""" |
|
0 commit comments