Source code for ska_sdp_resource_model.simulate.plot

"""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