Dashboard: fix plots

This commit is contained in:
phil 2024-03-25 10:10:58 +05:30
parent 5434c7d6ef
commit c8ca68e1a4
3 changed files with 28 additions and 20 deletions

View file

@ -1,7 +1,5 @@
import logging
from pathlib import Path
from json import dumps
from typing import Annotated
from fastapi import Depends, APIRouter, HTTPException, status, responses
from sqlalchemy.orm import selectinload
@ -10,7 +8,7 @@ import pandas as pd
import geopandas as gpd
from gisaf.config import conf
from gisaf.utils import NumpyEncoder
from gisaf.utils import dict_array_to_list
from gisaf.database import fastapi_db_session as db_session
from gisaf.models.authentication import User
from gisaf.models.dashboard import (
@ -138,16 +136,8 @@ async def get_dashboard_page(group: str, name: str,
'see debug message')
logger.exception(err)
if page.plot:
try:
plot = page.get_plot()
plotData = {
'data': [d.to_plotly_json() for d in plot.data],
'layout': plot.layout.to_plotly_json(),
}
except Exception as err:
logger.warning(f'Dashboard: cannot add plot for page {page.name}, '
'see debug message')
logger.exception(err)
else:
dp.plotData = dumps(plotData, cls=NumpyEncoder)
plot = page.get_plot()
## Convert manually numpy arrays to lists
dp.plotData = [dict_array_to_list(d.to_plotly_json()) for d in plot.data]
dp.plotLayout = plot.layout.to_plotly_json()
return dp

View file

@ -3,9 +3,11 @@ from pickle import loads
from pathlib import Path
from datetime import datetime
import logging
from typing import Any
# from typing import Any
from matplotlib.figure import Figure
from plotly.graph_objs._figure import Figure as PlotlyFigure
from sqlmodel import Field, Relationship, String, JSON
from pydantic import BaseModel
import pandas as pd
@ -110,18 +112,22 @@ class DashboardPageCommon:
#f'in {self.get_attachment_file_name()}')
return self.attachment
def get_page_df(self):
def get_page_df(self) -> pd.DataFrame | None:
"""
Get the dataframe of the page
"""
if not self.df:
return
return None
try:
return pd.read_pickle(BytesIO(self.df), compression=None)
df = pd.read_pickle(BytesIO(self.df), compression=None)
except KeyError:
raise NotADataframeError()
if isinstance(df, dict):
return None
else:
return df
def get_plot(self):
def get_plot(self) -> PlotlyFigure | None:
if self.plot is not None:
return loads(self.plot)
@ -293,7 +299,8 @@ class Dashboard(BaseModel):
html: str | None = None
attachment: str | None = None
dfData: list = []
plotData: str | None = None
plotData: list[dict] | None = None
plotLayout: dict[str, Any] | None = None
notebook: str | None = None
expandedPanes: list[str] | None = None
sections: list[DashboardSection] | None = None

View file

@ -83,6 +83,17 @@ gisTypeSymbolMap = {
# ).transform
def dict_array_to_list(d: dict) -> dict:
'''Convert any ndarray a dict to plain python list.
Useful for transforming a Dataframe to a serializable object'''
for k, v in d.items():
if isinstance(v, dict):
dict_array_to_list(v)
else:
if isinstance(v, ndarray):
d[k] = v.tolist()
return d
class NumpyEncoder(JSONEncoder):
"""
Encoder that can serialize numpy arrays and datetime objects