Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| import numpy as np | |
| import json | |
| import datetime | |
| import decimal | |
| def _ds(series, n=250): | |
| """Downsamples a time series to a maximum of `n` points for frontend rendering speed.""" | |
| if series is None: | |
| return series | |
| # Note: Ensure it's a pandas Series to prevent .iloc crashes on raw lists/arrays | |
| if not isinstance(series, (pd.Series, pd.DataFrame)): | |
| series = pd.Series(series) | |
| elif not series.index.is_unique: | |
| # Note: Deduplicate index to prevent Chart.js from rendering zig-zag lines | |
| series = series[~series.index.duplicated(keep='last')] | |
| if len(series) <= n: | |
| return series | |
| # Note: Use uniform np.linspace to avoid discontinuity seams from concatenating tails | |
| idx = np.round(np.linspace(0, len(series) - 1, n)).astype(int) | |
| return series.iloc[idx] | |
| def safe_json(obj): | |
| """ | |
| Safely serializes deep dictionaries containing NumPy/Pandas native types, | |
| Datetimes, NaNs, and NaTs for Chart.js parsing. | |
| """ | |
| def _fix(o): | |
| if o is None or o is pd.NA or o is pd.NaT: | |
| return None | |
| if isinstance(o, decimal.Decimal): | |
| return float(o) | |
| if isinstance(o, (float, np.floating)): | |
| return None if not np.isfinite(o) else float(o) | |
| if isinstance(o, (int, np.integer)): | |
| return int(o) | |
| if isinstance(o, (pd.Timestamp, datetime.datetime, datetime.date)): | |
| return str(o) | |
| if isinstance(o, dict): | |
| return {k: _fix(v) for k, v in o.items()} | |
| if isinstance(o, (list, tuple, np.ndarray, pd.Series, pd.Index)): | |
| return [_fix(v) for v in o] | |
| return o | |
| return json.dumps(_fix(obj)) | |