"""Module for plotting the simulation results."""
import plotly.express as px
from ska_sdp_resource_model.simulate.constants import (
HOURS_IN_DAY,
SECONDS_IN_1HR,
SECONDS_IN_DAY,
)
[docs]
def create_plot(resource_usage, column, title):
"""Create a line plot for the specified resource usage data.
Args:
resource_usage (pd.DataFrame):
A DataFrame containing resource usage data.
column (str):
The column name in `resource_usage` to plot on the y-axis.
title (str):
The title for the y-axis.
Returns:
plotly.graph_objects.Figure:
A Plotly figure object representing the line plot.
"""
resource_usage["time_days"] = resource_usage["time_s"] / SECONDS_IN_DAY
fig = px.line(
resource_usage,
x="time_days",
y=column,
color="iteration",
)
x_range = [
resource_usage["time_days"].min(),
resource_usage["time_days"].max(),
]
fig.update_layout(
yaxis_title=title,
xaxis={"range": x_range, "title": "Days"},
)
return fig
[docs]
def create_scheduling_blocks_gantt_plot(events_df, facet_row=None):
"""Create a Gantt-style plot events data.
Args:
events_df (pd.DataFrame):
A DataFrame containing event data.
facet_row (str):
The column name in `events_df` to use for the row facet, defaults
to None (no facets).
Returns:
fig (plotly.graph_objects.Figure):
A Plotly figure object representing the Gantt plot.
"""
events_df = events_df.drop_duplicates().sort_values("start")
events_df["SB_type"] = events_df["batch_name"].apply(
lambda x: x.split("_")[0][:2]
)
events_df["start_days"] = events_df["start"] / SECONDS_IN_DAY
events_df["end_days"] = events_df["end"] / SECONDS_IN_DAY
events_df["duration_days"] = events_df["duration"] / SECONDS_IN_DAY
x_range = [events_df["start_days"].min(), events_df["end_days"].max()]
block_filter = events_df["step"] == "block"
events_df = events_df[block_filter].sort_values(by=["start", "end"])
batch_order = events_df["batch_name"].unique()
fig = px.bar(
events_df,
base="start_days",
x="duration_days",
y="batch_name",
orientation="h",
color="SB_type",
labels={"SB_type": ""},
facet_row=facet_row,
)
fig.update_yaxes(
type="category",
categoryorder="array",
autorange="reversed",
categoryarray=batch_order,
title="Scheduling block instance ID",
)
fig.update_layout(
xaxis={"range": x_range, "title": "Days"},
yaxis={"showticklabels": True},
legend={
"orientation": "h",
"yanchor": "bottom",
"y": 1.02,
"xanchor": "right",
"x": 1,
},
)
return fig
[docs]
def create_observing_schedule_gantt_plot(observations_df):
"""Create a Gantt-style plot for observing schedule data.
Args:
observations_df (pd.DataFrame):
A DataFrame containing observing schedule data.
Returns:
fig (plotly.graph_objects.Figure):
A Plotly figure object representing the Gantt plot.
"""
observations_df["Row"] = 1
observations_df["duration"] = (
observations_df["End"] - observations_df["Start"]
) / HOURS_IN_DAY
observations_df["Start_days"] = observations_df["Start"] / HOURS_IN_DAY
observations_df["End_days"] = observations_df["End"] / HOURS_IN_DAY
x_range = [
observations_df["Start_days"].min(),
observations_df["End_days"].max(),
]
fig = px.bar(
observations_df,
base="Start_days",
x="duration",
y="Row",
orientation="h",
color="SB_type",
labels={"SB_type": ""},
)
fig.update_yaxes(
type="category",
categoryorder="total ascending",
title="",
autorange="reversed",
)
fig.update_layout(
xaxis={"range": x_range, "title": "Days"},
yaxis={"showticklabels": False},
legend={
"orientation": "h",
"yanchor": "bottom",
"y": 1.02,
"xanchor": "right",
"x": 1,
},
)
return fig
[docs]
def create_wait_time_plot(events_df, facet_col=None):
"""Create a strip plot showing waiting times.
Args:
events_df (pd.DataFrame):
A DataFrame containing event data.
facet_col (str):
The column name in `events_df` to use for the column facet,
defaults to None (no facets).
Returns:
fig (plotly.graph_objects.Figure):
A Plotly figure object representing the strip plot.
"""
events_df = events_df.drop_duplicates().sort_values("start")
events_df["duration"] = events_df["end"] - events_df["start"]
events_df["duration_hrs"] = events_df["duration"] / SECONDS_IN_1HR
events_df["SB_type"] = events_df["batch_name"].apply(
lambda x: x.split("_")[0][:2]
)
compute_wait_filter = events_df["step"].apply(
lambda x: "compute_wait" in x
)
capacity_wait_filter = events_df["step"].apply(
lambda x: "capacity_storage_wait_raw_visibilities" in x
)
data_product_wait_filter = events_df["step"].apply(
lambda x: "capacity_storage_wait_data_products" in x
)
performance_wait_filter = events_df["step"].apply(
lambda x: "performance_storage_wait" in x
)
events_df["wait"] = ""
events_df.loc[compute_wait_filter, "wait"] = "compute"
events_df.loc[capacity_wait_filter, "wait"] = "capacity_storage"
events_df.loc[performance_wait_filter, "wait"] = "performance_storage"
events_df.loc[data_product_wait_filter, "wait"] = "data_product_storage"
fig = px.strip(
events_df[events_df["wait"] != ""].sort_values("duration_hrs"),
x="wait",
y="duration_hrs",
color="SB_type",
facet_col=facet_col,
)
return fig
[docs]
def create_treemap(
config_df,
values_colname,
colour_colname,
title,
color_midpoint: float = None,
):
"""Create a treemap plot for the specified configuration data.
Args:
config_df (pd.DataFrame):
A DataFrame containing configuration data.
values_colname (str):
The column name in `config_df` to use for the treemap values.
colour_colname (str):
The column name in `config_df` to use for the treemap colours.
title (str):
The title for the treemap plot.
color_midpoint (float):
Midpoint for color (below blue, above red)
Returns:
fig (plotly.graph_objects.Figure):
A Plotly figure object representing the treemap plot.
"""
if color_midpoint is not None:
color_continuous_scale = "RdBu_r"
color_continuous_midpoint = color_midpoint
else:
color_continuous_scale = "magenta"
color_continuous_midpoint = None
fig = px.treemap(
config_df,
path=[
px.Constant("Scheduling block types"),
"sb_type",
"pipeline_steps",
],
values=values_colname,
color=colour_colname,
color_continuous_scale=color_continuous_scale,
color_continuous_midpoint=color_continuous_midpoint,
title=title,
)
fig.update_traces(root_color="lightgrey")
fig.update_layout(margin={"t": 50, "l": 25, "r": 25, "b": 25})
return fig