Skip to content

Commit

Permalink
Move tables code, more progress
Browse files Browse the repository at this point in the history
  • Loading branch information
tsmbland committed Jan 31, 2024
1 parent c43c401 commit 9fa5a43
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 215 deletions.
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ PyYAML==6.0.1
uritemplate==4.1.1
crispy-bootstrap4==2023.1
django-plotly-dash==2.2.2
dash-ag-grid
dash-ag-grid==2.4.0

## Legacy dependency versions
# asgiref==3.3.4
Expand Down
247 changes: 33 additions & 214 deletions validated/dash_apps/finished_apps/daily_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,18 @@
from decimal import Decimal

import plotly.express as px
import plotly.graph_objects as go
from dash import dcc, html
from dash_ag_grid import AgGrid
from django_plotly_dash import DjangoDash

from station.models import Station
from validated.functions import daily_validation, detail_list
from validated.tables import create_daily_table, create_detail_table
from variable.models import Variable

# Create a Dash app
app = DjangoDash("DailyValidation")

"""
DAILY DATA
"""

# Filters (in final app this will get data from forms)
station: Station = Station.objects.order_by("station_code")[7]
variable: Variable = Variable.objects.order_by("variable_code")[0]
Expand All @@ -26,7 +22,7 @@
minimum: Decimal = Decimal(-5)
maximum: Decimal = Decimal(28)

# Load data
# Daily data
data: dict = daily_validation(
station=station,
variable=variable,
Expand All @@ -36,13 +32,8 @@
maximum=maximum,
)

"""
DETAIL DATA
"""

# Detail data
date: datetime = datetime.strptime("2023-03-14", "%Y-%m-%d")

data_detail = detail_list(
station=station,
variable=variable,
Expand All @@ -51,219 +42,47 @@
maximum=maximum,
)

"""
PLOT
"""

x = data["series"]["measurement"]["time"]
y = data["series"]["measurement"]["average"]
plot = px.line(x=x, y=y)

"""
DAILY TABLE
"""


def get_columns_daily(value_columns):
styles = get_daily_style_data_conditional()

# Essential columns
essental_columns = [
{"field": "id", "headerName": "Id"},
{"field": "date", "headerName": "Date", **styles["date"]},
{"field": "percentage", "headerName": "Percnt.", **styles["percentage"]},
{
"field": "value_difference_error_count",
"headerName": "Diff. Err",
**styles["value_difference_error_count"],
},
]

# Optional columns
optional_columns = [
{"field": "sum", "headerName": "Sum"},
{"field": "average", "headerName": "Average", **styles["average"]},
{"field": "maximum", "headerName": "Max. of Maxs.", **styles["maximum"]},
{"field": "minimum", "headerName": "Min. of Mins.", **styles["minimum"]},
]

columns = essental_columns
columns += [d for d in optional_columns if d["field"] in value_columns]

# Action column
columns.append({"field": "action", "headerName": "Action"})
return columns


def get_daily_style_data_conditional():
styles = {}

styles["date"] = {
"cellStyle": {
"styleConditions": [
{
"condition": "params.data['date_error'] > 0",
"style": {"backgroundColor": "sandybrown"},
},
]
},
}

styles["percentage"] = {
"cellStyle": {
"styleConditions": [
{
"condition": "params.data['percentage_error']",
"style": {"backgroundColor": "sandybrown"},
},
]
},
}

styles["value_difference_error_count"] = {
"cellStyle": {
"styleConditions": [
{
"condition": "params.data['value_difference_error_count'] > 0",
"style": {"backgroundColor": "sandybrown"},
},
]
},
}

for field in ["sum", "average", "maximum", "minimum"]:
styles[field] = {
"cellStyle": {
"styleConditions": [
{
"condition": f"params.data['suspicious_{field}s_count'] > 0",
"style": {"backgroundColor": "sandybrown"},
},
]
},
}

return styles


def create_daily_table(data):
table_data = data["data"].copy()
for d in table_data:
d["action"] = "Action"

table = AgGrid(
id="table",
rowData=table_data,
columnDefs=get_columns_daily(value_columns=data["value_columns"]),
columnSize="sizeToFit",
defaultColDef={
"resizable": False,
"sortable": True,
"filter": False,
"checkboxSelection": {
"function": "params.column == params.columnApi.getAllDisplayedColumns()[0]"
},
"headerCheckboxSelection": {
"function": "params.column == params.columnApi.getAllDisplayedColumns()[0]"
},
},
dashGridOptions={"rowSelection": "multiple", "suppressRowClickSelection": True},
# Plot
plot = go.Figure()
plot.add_trace(
go.Scatter(
x=data["series"]["measurement"]["time"],
y=data["series"]["measurement"]["average"],
mode="lines",
name="Measurement",
)
return table


"""
DETAIL TABLE
"""


def get_columns_detail(value_columns):
styles = get_detail_style_data_conditional(value_columns)

columns = [
{"field": "id", "headerName": "Id"},
{"field": "time", "headerName": "Time", **styles["time"]},
]
columns += [
{"field": c, "headerName": c[0].upper() + c[1:], **styles[c]}
for c in value_columns
]
return columns


def get_detail_style_data_conditional(value_columns):
styles = {}

styles["time"] = {
"cellStyle": {
"styleConditions": [
{
"condition": f"params.data['time_lapse_status'] == {val}",
"style": {"backgroundColor": f"{col}"},
}
for val, col in zip([0, 2], ["sandybrown", "yellow"])
]
},
}

for field in value_columns:
styles[field] = {
"cellStyle": {
"styleConditions": [
{
"condition": f"params.data['{field}_error']",
"style": {"backgroundColor": "sandybrown"},
},
]
},
}

return styles


def create_detail_table(data_detail):
table = AgGrid(
id="table_detail",
rowData=data_detail["series"],
columnDefs=get_columns_detail(value_columns=data_detail["value_columns"]),
columnSize="sizeToFit",
defaultColDef={
"resizable": False,
"sortable": True,
"filter": True,
"checkboxSelection": {
"function": "params.column == params.columnApi.getAllDisplayedColumns()[0]"
},
"headerCheckboxSelection": {
"function": "params.column == params.columnApi.getAllDisplayedColumns()[0]"
},
},
dashGridOptions={"rowSelection": "multiple", "suppressRowClickSelection": True},
)
plot.add_trace(
go.Scatter(
x=data["series"]["validated"]["time"],
y=data["series"]["validated"]["average"],
mode="lines",
name="Validated",
)
return table


"""
LAYOUT
"""
)
plot.add_trace(
go.Scatter(
x=data["series"]["selected"]["time"],
y=data["series"]["selected"]["average"],
mode="lines",
name="Selected",
)
)

# Tables
table_daily = create_daily_table(data)
table_detail = create_detail_table(data_detail)

# Create layout
# Layout
app.layout = html.Div([table_daily, table_detail, dcc.Graph(figure=plot)])

# Callback: check boxes


"""
To do:
- Add action buttons
- Add error counts
- Have chackboxes selected by default
- Reformat time column
- Better filters
- Add outliers and value diffs to detail table
"""
Loading

0 comments on commit 9fa5a43

Please sign in to comment.