diff --git a/pq-tls-benchmark-framework/emulation-exp/code/kex/docs/Makefile b/pq-tls-benchmark-framework/emulation-exp/code/kex/docs/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..fefa43230760f95275c39462144369d9350bd6f8 --- /dev/null +++ b/pq-tls-benchmark-framework/emulation-exp/code/kex/docs/Makefile @@ -0,0 +1,3 @@ + +sequence_diagram.pdf: sequence_diagram.puml + plantuml -tpdf $< diff --git a/pq-tls-benchmark-framework/emulation-exp/code/kex/docs/sequence_diagram.pdf b/pq-tls-benchmark-framework/emulation-exp/code/kex/docs/sequence_diagram.pdf new file mode 100644 index 0000000000000000000000000000000000000000..50f677da2ba13b84ddbd7111e8f27ea4a396b5f2 Binary files /dev/null and b/pq-tls-benchmark-framework/emulation-exp/code/kex/docs/sequence_diagram.pdf differ diff --git a/pq-tls-benchmark-framework/emulation-exp/code/kex/docs/sequence_diagram.puml b/pq-tls-benchmark-framework/emulation-exp/code/kex/docs/sequence_diagram.puml new file mode 100644 index 0000000000000000000000000000000000000000..c30ee26c657d5c2c0ec531e06184e5701513296b --- /dev/null +++ b/pq-tls-benchmark-framework/emulation-exp/code/kex/docs/sequence_diagram.puml @@ -0,0 +1,43 @@ +@startuml sequence_diagram +activate Client +Client -> Client: do_tls_handshake() +activate Client + +' activate NetEm +' ' ||1|| +' deactivate NetEm + +Client -> Client: KeyGen() +activate Client +deactivate Client +Client -> NetEm: { Client Hello } + +' Client -> Client: waiting for response +' deactivate Client +' ... Client waiting ... +' deactivate Client + +activate NetEm +NetEm -> Server: { Client Hello } +' ... Server waiting ... +deactivate NetEm +activate Server +Server -> Server: generate_response() +activate Server +Server -> Server: Encaps() +activate Server +deactivate Server +deactivate Server +' Server -> NetEm: Server Hello, Encrypted Extensions, Certificate, Certificate Verify,Finished +Server -> NetEm: { Server Hello, Certificate, Finished } +deactivate Server + +activate NetEm +NetEm -> Client: { Server Hello, Certificate, Finished } +deactivate NetEm + +Client -> Client: Decaps() +activate Client +deactivate Client +deactivate Client +@enduml diff --git a/pq-tls-benchmark-framework/emulation-exp/code/kex/scripts/generate_graphs.py b/pq-tls-benchmark-framework/emulation-exp/code/kex/scripts/generate_graphs.py index 086e5f1934b01e8952bbd3480880b446e4799b99..6adcbba692502f4b8a4c3b0a4399ff4a0ccaab3c 100755 --- a/pq-tls-benchmark-framework/emulation-exp/code/kex/scripts/generate_graphs.py +++ b/pq-tls-benchmark-framework/emulation-exp/code/kex/scripts/generate_graphs.py @@ -1,6 +1,7 @@ #!/usr/bin/env python from functools import cmp_to_key +import colorsys import os import sys @@ -18,17 +19,17 @@ PLOTS_DIR = "plots" FEATHERS_DIR = "feathers" cmap = plt.cm.hsv - -# TODO use the riqr to make some graphs +# cmap = plt.colormaps.get_cmap("nipy_spectral") def main(): data = load_data() # generally they both only seconds for graphs when not generating for single algorithms + # plot_general_plots() # takes about 4 seconds plot_lines(data) # takes about 1:50 min # plot_static_data(data) # takes about 4 min - # plot_general_plots() # takes about 4 seconds + # plot_distributions(data) def load_data(): @@ -215,6 +216,7 @@ def filter_data( protocol: str | None = None, sec_level: str | list[str] | None = None, kem_alg: str | None = None, + drop_zero_columns: bool = True, ): filtered_data = data # print(filtered_data["kem_alg"] == "x25519") # is a boolean series @@ -241,7 +243,11 @@ def filter_data( ] return data.drop(columns=zero_columns_to_drop) - filtered_data = drop_columns_with_only_zero_values(filtered_data) + if drop_zero_columns and "measurements" in data.columns: + filtered_data = drop_columns_with_only_zero_values(filtered_data) + + # if drop_zero_columns: + # filtered_data = drop_columns_with_only_zero_values(filtered_data) # print(filtered_data["measurements"].head()) # print(filtered_data) @@ -269,7 +275,7 @@ def get_x_axis(scenario, data, length): case "rate_server": return data["srv_rate"] case "static": - return list(range(length)) + return pd.Series(range(length)) case _: print(f"NO MATCH FOUND FOR {scenario}", file=sys.stderr) sys.exit(1) @@ -289,6 +295,327 @@ def map_security_level_hybrid_together(sec_level: str): return None +def get_color_and_mode(kem_alg: str, combined_with_hybrids: bool = False): + # NOTE maybe just use hle colors directly from the start + primary_mode = "-" + secondary_mode = "--" if combined_with_hybrids else "-" + tertiary_mode = ":" if combined_with_hybrids else "--" + + secondary_lightness_factor = 0.9 if combined_with_hybrids else 1 + tertiary_lightness_factor = 0.8 if combined_with_hybrids else 0.9 + + a = 0.8 if combined_with_hybrids else 1 + + no_algos = 8 + match kem_alg: + case "secp256r1": + return cmap(0 / no_algos), primary_mode + case "secp384r1": + return cmap(0.3 / no_algos), primary_mode + case "secp521r1": + return cmap(0.6 / no_algos), primary_mode + case "x25519": + return cmap(0 / no_algos), secondary_mode + case "x448": + return cmap(0.3 / no_algos), secondary_mode + case "mlkem512": + return cmap(1 / no_algos), primary_mode + case "p256_mlkem512": + return ( + transform_cmap_color( + cmap(1 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "x25519_mlkem512": + return ( + transform_cmap_color( + cmap(1 / no_algos), + alpha_factor=a, + lightness_factor=tertiary_lightness_factor, + ), + tertiary_mode, + ) + case "mlkem768": + return cmap(1.3 / no_algos), primary_mode + case "p384_mlkem768": + return ( + transform_cmap_color( + cmap(1.3 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "x448_mlkem768": + return ( + transform_cmap_color( + cmap(1.3 / no_algos), + alpha_factor=a, + lightness_factor=tertiary_lightness_factor, + ), + tertiary_mode, + ) + case "mlkem1024": + return cmap(1.6 / no_algos), primary_mode + case "p521_mlkem1024": + return ( + transform_cmap_color( + cmap(1.6 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "bikel1": + return cmap(2 / no_algos), primary_mode + case "p256_bikel1": + return ( + transform_cmap_color( + cmap(2 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "x25519_bikel1": + return ( + transform_cmap_color( + cmap(2 / no_algos), + alpha_factor=a, + lightness_factor=tertiary_lightness_factor, + ), + tertiary_mode, + ) + case "bikel3": + return cmap(2.3 / no_algos), primary_mode + case "p384_bikel3": + return ( + transform_cmap_color( + cmap(2.3 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "x448_bikel3": + return ( + transform_cmap_color( + cmap(2.3 / no_algos), + alpha_factor=a, + lightness_factor=tertiary_lightness_factor, + ), + tertiary_mode, + ) + case "bikel5": + return cmap(2.6 / no_algos), primary_mode + case "p521_bikel5": + return ( + transform_cmap_color( + cmap(2.6 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "hqc128": + return cmap(4 / no_algos), primary_mode + case "p256_hqc128": + return ( + transform_cmap_color( + cmap(4 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "x25519_hqc128": + return ( + transform_cmap_color( + cmap(4 / no_algos), + alpha_factor=a, + lightness_factor=tertiary_lightness_factor, + ), + tertiary_mode, + ) + case "hqc192": + return cmap(4.3 / no_algos), primary_mode + case "p384_hqc192": + return ( + transform_cmap_color( + cmap(4.3 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "x448_hqc192": + return ( + transform_cmap_color( + cmap(4.3 / no_algos), + alpha_factor=a, + lightness_factor=tertiary_lightness_factor, + ), + tertiary_mode, + ) + case "hqc256": + return cmap(4.6 / no_algos), primary_mode + case "p521_hqc256": + return ( + transform_cmap_color( + cmap(4.6 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "frodo640aes": + return cmap(5 / no_algos), primary_mode + case "p256_frodo640aes": + return ( + transform_cmap_color( + cmap(5 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "x25519_frodo640aes": + return ( + transform_cmap_color( + cmap(5 / no_algos), + alpha_factor=a, + lightness_factor=tertiary_lightness_factor, + ), + tertiary_mode, + ) + case "frodo640shake": + return cmap(6 / no_algos), primary_mode + case "p256_frodo640shake": + return ( + transform_cmap_color( + cmap(6 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "x25519_frodo640shake": + return ( + transform_cmap_color( + cmap(6 / no_algos), + alpha_factor=a, + lightness_factor=tertiary_lightness_factor, + ), + tertiary_mode, + ) + case "frodo976aes": + return cmap(5.3 / no_algos), primary_mode + case "p384_frodo976aes": + return ( + transform_cmap_color( + cmap(5.3 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "x448_frodo976aes": + return ( + transform_cmap_color( + cmap(5.3 / no_algos), + alpha_factor=a, + lightness_factor=tertiary_lightness_factor, + ), + tertiary_mode, + ) + case "frodo976shake": + return cmap(6.3 / no_algos), primary_mode + case "p384_frodo976shake": + return ( + transform_cmap_color( + cmap(6.3 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "x448_frodo976shake": + return ( + transform_cmap_color( + cmap(6.3 / no_algos), + alpha_factor=a, + lightness_factor=tertiary_lightness_factor, + ), + tertiary_mode, + ) + case "frodo1344aes": + return cmap(5.6 / no_algos), primary_mode + case "p521_frodo1344aes": + return ( + transform_cmap_color( + cmap(5.6 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "frodo1344shake": + return cmap(6.6 / no_algos), primary_mode + case "p521_frodo1344shake": + return ( + transform_cmap_color( + cmap(6.6 / no_algos), + alpha_factor=a, + lightness_factor=secondary_lightness_factor, + ), + secondary_mode, + ) + case "x25519_mlkem768": + return ( + transform_cmap_color(cmap(7 / no_algos), alpha_factor=a), + primary_mode, + ) + case "p256_mlkem768": + return ( + transform_cmap_color( + cmap(7.5 / no_algos), lightness_factor=secondary_lightness_factor + ), + primary_mode, + ) + case "p384_mlkem1024": + return ( + transform_cmap_color( + cmap(7.99 / no_algos), lightness_factor=tertiary_lightness_factor + ), + primary_mode, + ) + case _: + print(f"NO COLOR MATCH FOUND FOR {kem_alg}", file=sys.stderr) + sys.exit(1) + + +def transform_cmap_color( + color, hue_shift=0, saturation_factor=1, lightness_factor=1, alpha_factor=1 +): + def value_between(minimum, value, maximum): + return max(minimum, min(value, maximum)) + + r, g, b, a = color + h, l, s = colorsys.rgb_to_hls(r, g, b) + h += hue_shift + l *= lightness_factor + l = value_between(0, l, 1) + s *= saturation_factor + s = value_between(0, s, 1) + r, g, b = colorsys.hls_to_rgb(h, l, s) + a *= alpha_factor + return r, g, b, a + + +# plots lines of different statistical values def plot_lines(data): def plot_lines_for_sec_level( data, line_type="median", combined_with_hybrids: bool = False @@ -323,7 +650,11 @@ def plot_lines(data): for idx, kem_alg in enumerate( filtered_data["kem_alg"].unique().sort_values() ): - color = cmap(idx / len(filtered_data["kem_alg"].unique())) + # color = cmap(idx / len(filtered_data["kem_alg"].unique())) + color, mode = get_color_and_mode( + kem_alg, combined_with_hybrids=combined_with_hybrids + ) + filtered_data_single_kem_alg = filter_data( filtered_data, kem_alg=kem_alg ) @@ -338,7 +669,7 @@ def plot_lines(data): # print(f"y: {y}") # plt.fill_between(x, filtered_data_single_kem_alg["qtl_25"], filtered_data_single_kem_alg["qtl_75"], alpha=0.2, color=color) - plt.plot(x, y, linestyle="-", marker=".", color=color, label=kem_alg) + plt.plot(x, y, linestyle=mode, marker=".", color=color, label=kem_alg) plt.ylim(bottom=0) plt.xlim(left=0) @@ -358,7 +689,7 @@ def plot_lines(data): subdir = "combined-with-hybrids/" appendix = "-combined-with-hybrids" plt.savefig( - f"{PLOTS_DIR}/{line_type}s-of-sec-level/{subdir}{line_type}-{row['scenario']}-{row['protocol']}-{row['sec_level']}{appendix}.png" + f"{PLOTS_DIR}/{line_type}s-of-sec-level/{subdir}{line_type}-{row['scenario']}-{row['protocol']}-{row['sec_level']}{appendix}.pdf" ) plt.close() @@ -397,25 +728,10 @@ def plot_lines(data): ) plt.savefig( - f"{PLOTS_DIR}/median-of-single-algorithm/median-{row['scenario']}-{row['protocol']}-{row['sec_level']}-{row['kem_alg']}.png" + f"{PLOTS_DIR}/median-of-single-algorithm/median-{row['scenario']}-{row['protocol']}-{row['sec_level']}-{row['kem_alg']}.pdf" ) plt.close() - # This does not yet seem like a good idea - def plot_median_against_iqr(data): - plt.figure() - plt.hexbin(data["median"], data["iqr"], gridsize=50) - print(data["iqr"].describe()) - print(data["median"].describe()) - # get the line with the maximum median - max_median = data["median"].idxmax() - print(data.iloc[max_median]) - plt.savefig(f"{PLOTS_DIR}/median_against_iqr_hexbin.png") - - plt.figure() - plt.hist2d(data["median"], data["iqr"], bins=50) - plt.savefig(f"{PLOTS_DIR}/median_against_iqr_hist2d.png") - do_graphs_for = [ "median", "qtl_25", @@ -428,6 +744,7 @@ def plot_lines(data): "kurtosis", ] for thing in do_graphs_for: + print(f"Generating graphs for {thing}") plot_lines_for_sec_level(data, line_type=thing, combined_with_hybrids=False) plot_lines_for_sec_level(data, line_type=thing, combined_with_hybrids=True) @@ -435,6 +752,113 @@ def plot_lines(data): # plot_median_against_iqr(data) +# plots distributions of the individual data points +def plot_distributions(data): + os.makedirs( + f"{PLOTS_DIR}/distributions/single", + mode=0o777, + exist_ok=True, + ) + + def plot_multiple_violin_plots(data, filtered: bool = False): + os.makedirs( + f"{PLOTS_DIR}/distributions/filtered", + mode=0o777, + exist_ok=True, + ) + + unique_combinations = data[ + ["scenario", "protocol", "sec_level", "kem_alg"] + ].drop_duplicates() + # print(unique_combinations) + for _, row in unique_combinations.iterrows(): + filtered_data = filter_data( + data, + scenario=row["scenario"], + protocol=row["protocol"], + sec_level=row["sec_level"], + kem_alg=row["kem_alg"], + ) + print( + f"scenario: {row['scenario']}, protocol: {row['protocol']}, sec_level: {row['sec_level']}, kem_alg: {row['kem_alg']}, len: {len(filtered_data)}" + ) + + if filtered: + filtered_data = pd.concat( + [ + filtered_data.iloc[[0]], + filtered_data.iloc[3:-4:4], + filtered_data.iloc[[-1]], + ] + ) + print(filtered_data) + + plt.figure() + x = get_x_axis(row["scenario"], filtered_data, len(filtered_data)) + x = x.to_list() + # print(x) + width = 0.5 if not filtered else 2 + plt.violinplot( + filtered_data["measurements"], + positions=x, + showmedians=True, + widths=width, + ) + # make the median line transparent + # for pc in plt.gca().collections: + # pc.set_alpha(0.5) + + plt.ylim(bottom=0) + plt.xlim(left=0) + plt.xlabel(row["scenario"]) + plt.ylabel(f"Time-to-first-byte (ms)") + + subdir = "filtered/" if filtered else "" + appendix = "-filtered" if filtered else "" + plt.savefig( + f"{PLOTS_DIR}/distributions/{subdir}multiple-violin-plots-for-{row['scenario']}-{row['protocol']}-{row['sec_level']}-{row['kem_alg']}{appendix}.pdf" + ) + plt.close() + + def plot_single_violin_plot(data): + unique_combinations = data[ + ["scenario", "protocol", "sec_level", "kem_alg"] + ].drop_duplicates() + for _, row in unique_combinations.iterrows(): + filtered_data = filter_data( + data, + scenario=row["scenario"], + protocol=row["protocol"], + sec_level=row["sec_level"], + kem_alg=row["kem_alg"], + ) + print( + f"scenario: {row['scenario']}, protocol: {row['protocol']}, sec_level: {row['sec_level']}, kem_alg: {row['kem_alg']}" + ) + for _, row in filtered_data.iterrows(): + if row["scenario"] == "static": + continue + value = get_x_axis(row["scenario"], row, 1) + print(value) + + plt.figure() + plt.violinplot(row["measurements"], showmedians=True) + # plt.ylim(bottom=0) + # plt.xlim(left=0) + plt.xlabel("Dichte") + plt.ylabel(f"Time-to-first-byte (ms)") + + plt.savefig( + f"{PLOTS_DIR}/distributions/single/single-violin-plot-for-{row['scenario']}-{row['protocol']}-{row['sec_level']}-{row['kem_alg']}-{value}.pdf" + ) + plt.close() + # return + + plot_multiple_violin_plots(data, filtered=False) + plot_multiple_violin_plots(data, filtered=True) + # plot_single_violin_plot(data) # takes an age + + # TODO make a violinplot/eventplot for many algos in static scenario def plot_static_data(data): os.makedirs(f"{PLOTS_DIR}/static/single", mode=0o777, exist_ok=True) @@ -492,9 +916,12 @@ def plot_static_data(data): # ) # Get the median irqs for all algorithms + # print(row["protocol"], row["sec_level"]) # print(iqrs) # print(iqrs["iqr"].describe()) - # print("Median: ", iqrs["iqr"].median()) + # print("Median:", iqrs["iqr"].median()) + # print("IQR:", scipy.stats.iqr(iqrs["iqr"])) + # print() plt.xticks( range(len(filtered_data["kem_alg"].unique())), @@ -513,7 +940,7 @@ def plot_static_data(data): os.path.join( PLOTS_DIR, "static", - f"boxplots-of-medians-for-static-{row['protocol']}-{sec_level_string}.png", + f"boxplots-of-medians-for-static-{row['protocol']}-{sec_level_string}.pdf", ) ) plt.close() @@ -522,6 +949,7 @@ def plot_static_data(data): unique_combinations = data[ ["scenario", "protocol", "sec_level", "kem_alg"] ].drop_duplicates() + unique_combinations = filter_data(unique_combinations, scenario="static") for idx, row in unique_combinations.iterrows(): filtered_data = filter_data( data, @@ -531,45 +959,96 @@ def plot_static_data(data): kem_alg=row["kem_alg"], ) - plt.figure() - plt.boxplot(filtered_data["median"]) - plt.savefig( - os.path.join( - PLOTS_DIR, - "static", - "single", - f"boxplot-of-medians-for-{row['scenario']}-{row['protocol']}-{row['sec_level']}-{row['kem_alg']}.png", + def boxplot_of_medians_for_configuration(filtered_data, row): + plt.figure() + plt.boxplot(filtered_data["median"]) + plt.savefig( + os.path.join( + PLOTS_DIR, + "static", + "single", + f"boxplot-of-medians-for-{row['scenario']}-{row['protocol']}-{row['sec_level']}-{row['kem_alg']}.pdf", + ) ) - ) - plt.close() - - plt.figure() - plt.violinplot(filtered_data["measurements"], showmedians=True) - plt.savefig( - os.path.join( - PLOTS_DIR, - "static", - "single", - f"multiple-violin-plots-for-{row['scenario']}-{row['protocol']}-{row['sec_level']}-{row['kem_alg']}.png", + plt.close() + + # why the density of violin plot and kde plot differ, while using the same scott kde just sideways: + # Dove deep into the implementation from matplotlib and scipy, and they seem to calculate scotts factor in the same way, so dunno + def condensed_violin_plot_for_configuration(filtered_data, row): + # for multiple runs of the same static scenario, data taken together + measurements_flattend = filtered_data["measurements"].explode().tolist() + # print(filtered_data["measurements"].explode()) + # print(len(measurements_flattend)) + plt.figure() + plt.violinplot(measurements_flattend, showmedians=True) + plt.ylabel("Time-to-first-byte (ms)") + plt.xlabel("Dichte") + plt.savefig( + os.path.join( + PLOTS_DIR, + "static", + "single", + f"condensed-violin-plot-for-{len(measurements_flattend)}-measurements-of-{row['scenario']}-{row['protocol']}-{row['sec_level']}-{row['kem_alg']}.pdf", + ) ) - ) - plt.close() + plt.close() + + def condensed_histogram_plot_for_configuration(filtered_data, row): + measurements_flattend = filtered_data["measurements"].explode().tolist() + plt.figure() + plt.hist(measurements_flattend, bins=100, density=True) + plt.xlabel("Time-to-first-byte (ms)") + plt.ylabel("Dichte") + + plt.savefig( + os.path.join( + PLOTS_DIR, + "static", + "single", + f"condensed-histogram-plot-for-{len(measurements_flattend)}-measurements-of-{row['scenario']}-{row['protocol']}-{row['sec_level']}-{row['kem_alg']}.pdf", + ) + ) + plt.close() - # for multiple runs of the same static scenario, data taken together - measurements_flattend = filtered_data["measurements"].explode().tolist() - # print(filtered_data["measurements"].explode()) - # print(len(measurements_flattend)) - plt.figure() - plt.violinplot(measurements_flattend, showmedians=True) - plt.savefig( - os.path.join( - PLOTS_DIR, - "static", - "single", - f"condensed-violin-plot-for-{len(measurements_flattend)}-measurements-of-{row['scenario']}-{row['protocol']}-{row['sec_level']}-{row['kem_alg']}.png", + def condensed_kernel_density_estimate_plot_for_configuration( + filtered_data, row + ): + measurements_flattend = filtered_data["measurements"].explode().tolist() + plt.figure() + + kde = scipy.stats.gaussian_kde(measurements_flattend) + xmin = min(measurements_flattend) - 0.2 + xmax = max(measurements_flattend) + 0.1 + x = np.linspace( + xmin, + xmax, + 1000, ) - ) - plt.close() + kde_values = kde(x) + + plt.plot(x, kde_values) + plt.fill_between(x, kde_values, alpha=0.5) + + plt.xlabel("Time-to-first-byte (ms)") + plt.ylabel("Dichte") + plt.xlim([xmin, xmax]) + plt.ylim([0, max(kde_values) + 0.1]) + + plt.savefig( + os.path.join( + PLOTS_DIR, + "static", + "single", + f"condensed-kde-plot-for-{len(measurements_flattend)}-measurements-of-{row['scenario']}-{row['protocol']}-{row['sec_level']}-{row['kem_alg']}.pdf", + ) + ) + plt.close() + + boxplot_of_medians_for_configuration(filtered_data, row) + condensed_violin_plot_for_configuration(filtered_data, row) + condensed_histogram_plot_for_configuration(filtered_data, row) + condensed_kernel_density_estimate_plot_for_configuration(filtered_data, row) + # return plot_static_data_for_multiple_algorithms(data) plot_static_data_for_single_algorithms(data) @@ -643,9 +1122,9 @@ def plot_general_plots(): plt.ylabel("Performance (µs)") name = ( - "scatter-of-bytes-sent-against-kem-performance-with-hybrids.png" + "scatter-of-bytes-sent-against-kem-performance-with-hybrids.pdf" if with_hybrids - else "scatter-of-bytes-sent-against-kem-performance.png" + else "scatter-of-bytes-sent-against-kem-performance.pdf" ) plt.savefig( os.path.join(PLOTS_DIR, "general", name), @@ -718,13 +1197,31 @@ def plot_general_plots(): with_hybrids_string = "-with-hybrids" if with_hybrids else "" with_lines_string = "-with-lines" if with_lines else "" - name = f"scatter-of-public-key-against-ciphertext-length{with_hybrids_string}{with_lines_string}.png" + name = f"scatter-of-public-key-against-ciphertext-length{with_hybrids_string}{with_lines_string}.pdf" plt.savefig( os.path.join(PLOTS_DIR, "general", name), dpi=300, ) plt.close() + # This does not yet seem like a good idea + # TODO use the riqr to make some graphs + def plot_median_against_iqr(data): + plt.figure() + plt.hexbin(data["median"], data["iqr"], gridsize=50) + print(data["iqr"].describe()) + print(data["median"].describe()) + # get the line with the maximum median + max_median = data["median"].idxmax() + print(data.iloc[max_median]) + plt.savefig(f"{PLOTS_DIR}/general/median_against_iqr_hexbin.pdf") + plt.close() + + plt.figure() + plt.hist2d(data["median"], data["iqr"], bins=50) + plt.savefig(f"{PLOTS_DIR}/general/median_against_iqr_hist2d.pdf") + plt.close() + plot_send_bytes_against_kem_performance(df, with_hybrids=False) plot_send_bytes_against_kem_performance(df, with_hybrids=True)