all datetime columns changed to timestamp, change from json to faster orjson

This commit is contained in:
David Brazda
2024-06-12 13:33:50 +02:00
parent ed7ff29771
commit c29b1c5535
4 changed files with 51 additions and 14 deletions

View File

@ -275,6 +275,18 @@ class SeriesCommon(Pane):
if not pd.api.types.is_datetime64_any_dtype(df['time']): if not pd.api.types.is_datetime64_any_dtype(df['time']):
df['time'] = pd.to_datetime(df['time']) df['time'] = pd.to_datetime(df['time'])
df['time'] = df['time'].astype('int64') / 10 ** 9 #removed integer divison // 10 ** 9 to keep subseconds precision df['time'] = df['time'].astype('int64') / 10 ** 9 #removed integer divison // 10 ** 9 to keep subseconds precision
# if 'updated' in df.columns:
# df['updated'] = pd.to_datetime(df['updated']).astype('int64') / 10**9
# Iterate over all columns and convert any additional datetime columns to timestamps (for example updated)
for col in df.columns:
# Skip columns that are explicitly managed elsewhere or meant to be excluded
if col == 'time' or not pd.api.types.is_datetime64_any_dtype(df[col]):
continue
# Convert datetime to timestamp with nanosecond precision after the decimal
df[col] = pd.to_datetime(df[col]).astype('int64') / 10**9
return df return df
def _series_datetime_format(self, series: pd.Series, exclude_lowercase=None): def _series_datetime_format(self, series: pd.Series, exclude_lowercase=None):

View File

@ -1,4 +1,4 @@
import json import orjson
class ToolBox: class ToolBox:
@ -22,14 +22,14 @@ class ToolBox:
""" """
if not self.drawings.get(tag): if not self.drawings.get(tag):
return return
self.run_script(f'if ({self.id}.toolBox) {self.id}.toolBox.loadDrawings({json.dumps(self.drawings[tag])})') self.run_script(f'if ({self.id}.toolBox) {self.id}.toolBox.loadDrawings({orjson.dumps(self.drawings[tag])})')
def import_drawings(self, file_path): def import_drawings(self, file_path):
""" """
Imports a list of drawings stored at the given file path. Imports a list of drawings stored at the given file path.
""" """
with open(file_path, 'r') as f: with open(file_path, 'r') as f:
json_data = json.load(f) json_data = orjson.load(f)
self.drawings = json_data self.drawings = json_data
def export_drawings(self, file_path): def export_drawings(self, file_path):
@ -37,9 +37,9 @@ class ToolBox:
Exports the current list of drawings to the given file path. Exports the current list of drawings to the given file path.
""" """
with open(file_path, 'w+') as f: with open(file_path, 'w+') as f:
json.dump(self.drawings, f, indent=4) orjson.dump(self.drawings, f, indent=4)
def _save_drawings(self, drawings): def _save_drawings(self, drawings):
if not self._save_under: if not self._save_under:
return return
self.drawings[self._save_under.value] = json.loads(drawings) self.drawings[self._save_under.value] = orjson.loads(drawings)

View File

@ -1,5 +1,5 @@
import asyncio import asyncio
import json import orjson
from datetime import datetime from datetime import datetime
from random import choices from random import choices
from typing import Literal, Union from typing import Literal, Union
@ -36,30 +36,54 @@ def parse_event_message(window, string):
return func, args return func, args
# def js_data(data: Union[pd.DataFrame, pd.Series]):
# if isinstance(data, pd.DataFrame):
# d = data.to_dict(orient='records')
# filtered_records = [{k: v for k, v in record.items() if v is not None and not pd.isna(v)} for record in d]
# else:
# d = data.to_dict()
# filtered_records = {k: v for k, v in d.items()}
# return json.dumps(filtered_records)
def js_data(data: Union[pd.DataFrame, pd.Series]): def js_data(data: Union[pd.DataFrame, pd.Series]):
if isinstance(data, pd.DataFrame): if isinstance(data, pd.DataFrame):
d = data.to_dict(orient='records') # Converting DataFrame to a list of dictionaries, filtering out NaN values
filtered_records = [{k: v for k, v in record.items() if v is not None and not pd.isna(v)} for record in d] filtered_records = data.dropna().to_dict(orient='records')
else: else:
d = data.to_dict() # For pd.Series, convert to dict and drop NaN values
filtered_records = {k: v for k, v in d.items()} filtered_records = data.dropna().to_dict()
return json.dumps(filtered_records, indent=2)
# Serialize using orjson, which returns bytes
# Decode bytes to string if necessary (JavaScript consumption requires string)
return orjson.dumps(filtered_records).decode('utf-8')
def snake_to_camel(s: str): def snake_to_camel(s: str):
components = s.split('_') components = s.split('_')
return components[0] + ''.join(x.title() for x in components[1:]) return components[0] + ''.join(x.title() for x in components[1:])
# def js_json(d: dict):
# filtered_dict = {}
# for key, val in d.items():
# if key in ('self') or val in (None,):
# continue
# if '_' in key:
# key = snake_to_camel(key)
# filtered_dict[key] = val
# return f"JSON.parse('{json.dumps(filtered_dict)}')"
def js_json(d: dict): def js_json(d: dict):
filtered_dict = {} filtered_dict = {}
for key, val in d.items(): for key, val in d.items():
if key in ('self') or val in (None,): if key == 'self' or val in (None,):
continue continue
if '_' in key: if '_' in key:
key = snake_to_camel(key) key = snake_to_camel(key)
filtered_dict[key] = val filtered_dict[key] = val
return f"JSON.parse('{json.dumps(filtered_dict)}')"
# Serialize the dictionary using orjson, automatically handling types that orjson can serialize
# Decode the bytes to string for use in JavaScript, escaping single quotes for JavaScript consumption
json_str = orjson.dumps(filtered_dict).decode('utf-8').replace("'", "\\'")
return f"JSON.parse('{json_str}')"
def jbool(b: bool): return 'true' if b is True else 'false' if b is False else None def jbool(b: bool): return 'true' if b is True else 'false' if b is False else None

View File

@ -5,12 +5,13 @@ with open('README.md', 'r', encoding='utf-8') as f:
setup( setup(
name='lightweight_charts', name='lightweight_charts',
version='2.0.15', version='2.0.16',
packages=find_packages(), packages=find_packages(),
python_requires='>=3.8', python_requires='>=3.8',
install_requires=[ install_requires=[
'pandas', 'pandas',
'pywebview>=5.0.5', 'pywebview>=5.0.5',
'orjson'
], ],
package_data={ package_data={
'lightweight_charts': ['js/*'], 'lightweight_charts': ['js/*'],