Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add line plots #325

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
10 changes: 7 additions & 3 deletions post-processing/config_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ def from_template(self):
return self(dict({
"plot_type": None,
"title": None,
"x_axis": {"value": None, "units": {"custom": None}},
"y_axis": {"value": None, "units": {"custom": None}, "scaling": {"custom": None}},
"x_axis": {"value": None, "units": {"custom": None}, "range": {"use_default": True, "min": None, "max": None}},
"y_axis": {"value": None, "units": {"custom": None}, "scaling": {"custom": None}, "range": {"use_default": True, "min": None, "max": None}},
"filters": {"and": [], "or": []},
"series": [],
"column_types": {},
Expand Down Expand Up @@ -245,7 +245,7 @@ def read_config(config: dict):
if not plot_type:
raise KeyError("Missing plot type information.")
elif (plot_type != 'generic') and (plot_type != 'line'):
raise RuntimeError("plot_type must be one of: 'generic', 'line'")
raise RuntimeError("Plot type must be one of 'generic' or 'line'.")

# check plot title information
if not config.get("title"):
Expand All @@ -258,6 +258,8 @@ def read_config(config: dict):
raise KeyError("Missing x-axis value information.")
if not config.get("x_axis").get("units"):
raise KeyError("Missing x-axis units information.")
if not config.get("x_axis").get("range"):
raise KeyError("Missing x-axis range information.")
if (config.get("x_axis").get("units").get("column") is not None and
config.get("x_axis").get("units").get("custom") is not None):
raise RuntimeError(
Expand All @@ -270,6 +272,8 @@ def read_config(config: dict):
raise KeyError("Missing y-axis value information.")
if not config.get("y_axis").get("units"):
raise KeyError("Missing y-axis units information.")
if not config.get("y_axis").get("range"):
raise KeyError("Missing y-axis range information.")
if (config.get("y_axis").get("units").get("column") is not None and
config.get("y_axis").get("units").get("custom") is not None):
raise RuntimeError(
Expand Down
35 changes: 26 additions & 9 deletions post-processing/plot_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import numpy as np
import pandas as pd
from pandas.api.types import is_datetime64_any_dtype as is_datetime
from bokeh.models import HoverTool, Legend
from bokeh.models.sources import ColumnDataSource
from bokeh.palettes import viridis
Expand All @@ -12,6 +13,29 @@
from titlecase import titlecase
import itertools

def get_axis_min_max(df, axis, column):
axis_range = axis["range"]
axis_min = axis_range["min"] if axis_range["min"] != 'None' else None
axis_max = axis_range["max"] if axis_range["max"] != 'None' else None

#FIXME: str types and user defined datetime ranges not currently supported
# use defaults if type is datetime
axis_min_element = np.nanmin(df[column])
axis_max_element = np.nanmax(df[column])
if (is_datetime(df[column])):
datetime_range = axis_max_element - axis_min_element
buffer_time = datetime_range*0.2
axis_min = axis_min_element - buffer_time
axis_max = axis_max_element + buffer_time
else:
if not (axis_min and axis_max):
axis_min = (axis_min_element*0.6 if min(df[column]) >= 0
else math.floor(axis_min_element*1.2))
axis_max = (axis_max_element*0.6 if max(df[column]) <= 0
else math.ceil(axis_max_element*1.2))
connoraird marked this conversation as resolved.
Show resolved Hide resolved

return axis_min, axis_max

def plot_line_chart(title, df: pd.DataFrame, x_axis, y_axis, series_filters):
"""
Create a line chart for the supplied data using bokeh.
Expand All @@ -27,15 +51,8 @@ def plot_line_chart(title, df: pd.DataFrame, x_axis, y_axis, series_filters):
x_column, x_label = get_axis_labels(df, x_axis, series_filters)
y_column, y_label = get_axis_labels(df, y_axis, series_filters)

# adjust axis ranges
min_y = (0 if min(df[y_column]) >= 0
else math.floor(np.nanmin(df[y_column])*1.2))
max_y = (0 if max(df[y_column]) <= 0
else math.ceil(np.nanmax(df[y_column])*1.2))
min_x = (0 if min(df[x_column]) >= 0
else math.floor(np.nanmin(df[x_column])*1.2))
max_x = (0 if max(df[x_column]) <= 0
else math.ceil(np.nanmax(df[x_column])*1.2))
min_x, max_x = get_axis_min_max(df, x_axis, x_column)
min_y, max_y = get_axis_min_max(df, y_axis, y_column)

# create html file to store plot in
output_file(filename=os.path.join(
Expand Down
23 changes: 23 additions & 0 deletions post-processing/streamlit_post_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,16 @@ def axis_select(label: str, axis: dict):

# units select
units_select(label, axis)

# axis range
use_default_ranges = st.checkbox("Use default ranges", axis.get("range").get("use_default"), key="{0}_axis_range_use_default".format(label))
if not use_default_ranges:
axis_range_min, axis_range_max = st.columns(2)
with axis_range_min:
st.number_input("Minimum", key="{0}_axis_range_min".format(label))
with axis_range_max:
st.number_input("Maximum", key="{0}_axis_range_max".format(label))
connoraird marked this conversation as resolved.
Show resolved Hide resolved

# scaling select
if label == "y":
st.write("---")
Expand Down Expand Up @@ -294,6 +304,9 @@ def update_axes():
x_column = state.x_axis_column
x_units_column = state.x_axis_units_column
x_units_custom = state.x_axis_units_custom
x_range_use_default = state.x_axis_range_use_default
x_range_min = None if x_range_use_default else state.x_axis_range_min
x_range_max = None if x_range_use_default else state.x_axis_range_max

y_column = state.y_axis_column
y_units_column = state.y_axis_units_column
Expand All @@ -302,6 +315,9 @@ def update_axes():
y_scaling_series = state.y_axis_scaling_series
y_scaling_x = state.y_axis_scaling_x_value
y_scaling_custom = state.y_axis_custom_scaling_val
y_range_use_default = state.y_axis_range_use_default
y_range_min = None if y_range_use_default else state.y_axis_range_min
y_range_max = None if y_range_use_default else state.y_axis_range_max

# update columns
config.x_axis["value"] = x_column
Expand All @@ -321,6 +337,13 @@ def update_axes():
config.y_axis["units"] = {"column": y_units_column}
config.column_types[y_units_column] = "str"

config.x_axis["range"]["use_default"] = x_range_use_default
config.x_axis["range"]["min"] = x_range_min
config.x_axis["range"]["max"] = x_range_max
config.y_axis["range"]["use_default"] = y_range_use_default
config.y_axis["range"]["min"] = y_range_min
config.y_axis["range"]["max"] = y_range_max

# update scaling
config.y_axis["scaling"] = {"custom": y_scaling_custom if y_scaling_custom else None}
if not y_scaling_custom and y_scaling_column:
Expand Down
Loading