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

View file

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

View file

@ -83,6 +83,17 @@ gisTypeSymbolMap = {
# ).transform # ).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): class NumpyEncoder(JSONEncoder):
""" """
Encoder that can serialize numpy arrays and datetime objects Encoder that can serialize numpy arrays and datetime objects