From 301c3e5be4be18d9700404ec6a4a5a013b95def3 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee <5462944+youngjoon-lee@users.noreply.github.com> Date: Mon, 5 Aug 2024 22:10:34 +0900 Subject: [PATCH] add cross-experiment plots --- mixnet/cmd/queuesim_plot_crossexp.py | 20 +++++++ mixnet/queuesim/plot.py | 79 +++++++++++++++++++++++----- 2 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 mixnet/cmd/queuesim_plot_crossexp.py diff --git a/mixnet/cmd/queuesim_plot_crossexp.py b/mixnet/cmd/queuesim_plot_crossexp.py new file mode 100644 index 0000000..67e37b7 --- /dev/null +++ b/mixnet/cmd/queuesim_plot_crossexp.py @@ -0,0 +1,20 @@ +import argparse + +import pandas as pd + +from queuesim.paramset import ExperimentID, SessionID +from queuesim.plot import draw_cross_experiment_plots, draw_plots + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Draw cross-experiment plots", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "--csv-paths", type=str, required=True, help="Experiment result CSV paths" + ) + parser.add_argument("--outdir", type=str, required=True, help="output directory") + args = parser.parse_args() + + dfs = [pd.read_csv(path) for path in args.csv_paths.split(",")] + draw_cross_experiment_plots(dfs, args.outdir) diff --git a/mixnet/queuesim/plot.py b/mixnet/queuesim/plot.py index 55ae965..f28b553 100644 --- a/mixnet/queuesim/plot.py +++ b/mixnet/queuesim/plot.py @@ -57,15 +57,6 @@ def draw_plots( ) -def __param_set_legend(row): - legend = "" - for i, param in enumerate(PARAM_SET): - if i > 0: - legend += ", " - legend += f"{param}:{row[param]}" - return legend - - def __overview_by_queue_type( df: pd.DataFrame, exp_id: ExperimentID, @@ -97,14 +88,24 @@ def __impact_of_param_by_queue_type( ) -def __draw_plot_by_queue_type(df: pd.DataFrame, title: str, out_path: str): +def __draw_plot_by_queue_type( + df: pd.DataFrame, title: str, out_path: str, legend_columns: list[str] = PARAM_SET +): # Add a column that will be used as a legend - df["parameter_set"] = df.apply(__param_set_legend, axis=1) + def __create_legend_value(row): + legend = "" + for i, param in enumerate(legend_columns): + if i > 0: + legend += ", " + legend += f"{param}:{row[param]}" + return legend + + df["legend"] = df.apply(__create_legend_value, axis=1) # Prepare DataFrame in long format for seaborn boxplot long_format_df = pd.melt( df, - id_vars=["queue_type", "parameter_set"], + id_vars=["queue_type", "legend"], value_vars=BOXPLOT_VALUE_VARS, var_name="dtime_metric", value_name="dtime", @@ -112,7 +113,7 @@ def __draw_plot_by_queue_type(df: pd.DataFrame, title: str, out_path: str): # Plotting plt.figure(figsize=(15, 10)) - sns.boxplot(data=long_format_df, x="queue_type", y="dtime", hue="parameter_set") + sns.boxplot(data=long_format_df, x="queue_type", y="dtime", hue="legend") plt.title(title) plt.xlabel("Queue Type") plt.ylabel("Dissemination Time") @@ -131,3 +132,55 @@ def __draw_plot_by_queue_type(df: pd.DataFrame, title: str, out_path: str): assert not os.path.exists(out_path) plt.savefig(out_path) plt.draw() + print(f"Saved plot to {out_path}") + + +def draw_cross_experiment_plots(dfs: list[pd.DataFrame], outdir: str): + assert os.path.exists(outdir) + assert len(dfs) == len(ExperimentID) + + # Common filtering conditions + common_conditions = { + "num_nodes": 80, + "peering_degree": 16, + "min_queue_size": 40, + "transmission_rate": 40, + } + # Define the filtering conditions for each DataFrame + conditions = [ + {"num_senders": 1, "num_sent_msgs": 1}, + {"num_senders": 1, "num_sent_msgs": 8}, + {"num_senders": 8, "num_sent_msgs": 1}, + {"num_senders": 8, "num_sent_msgs": 8}, + ] + + filtered_dfs: list[pd.DataFrame] = [] + for exp_idx, (df, condition) in enumerate(zip(dfs, conditions)): + # Combine common and specific conditions + all_conditions = {**common_conditions, **condition} + # Filter the DataFrame + filtered_df = pd.DataFrame( + df[ + (df["num_nodes"] == all_conditions["num_nodes"]) + & (df["peering_degree"] == all_conditions["peering_degree"]) + & (df["min_queue_size"] == all_conditions["min_queue_size"]) + & (df["transmission_rate"] == all_conditions["transmission_rate"]) + & (df["num_senders"] == all_conditions["num_senders"]) + & (df["num_sent_msgs"] == all_conditions["num_sent_msgs"]) + ] + ) + filtered_df["experiment"] = ExperimentID(exp_idx + 1).value + filtered_dfs.append( + pd.DataFrame( + filtered_df[ + ["experiment"] + PARAM_SET + ["queue_type"] + BOXPLOT_VALUE_VARS + ] + ) + ) + + __draw_plot_by_queue_type( + pd.concat(filtered_dfs), + "Comparisons by Experiment and Queue Type", + f"{outdir}/cross_experiment_plot.png", + legend_columns=["experiment"] + PARAM_SET, + )