diff --git a/pq-tls-benchmark-framework/emulation-exp/code/kex/saved/qlogdir/cquiche-bbr2-minimal-cwnd-is-2.sqlog b/pq-tls-benchmark-framework/emulation-exp/code/kex/saved/qlogdir/cquiche-bbr2-minimal-cwnd-is-2.sqlog
new file mode 100644
index 0000000000000000000000000000000000000000..d6a4381e1069240e8779556e724d7d4084422875
--- /dev/null
+++ b/pq-tls-benchmark-framework/emulation-exp/code/kex/saved/qlogdir/cquiche-bbr2-minimal-cwnd-is-2.sqlog
@@ -0,0 +1,37 @@
+{"qlog_version":"0.3","qlog_format":"JSON-SEQ","title":"cquiche_s_timer qlog","description":"cquiche_s_timer qlog id=172ce7b0686cf7d3cd8e9bef4203a68030375ceb","trace":{"vantage_point":{"type":"client"},"title":"cquiche_s_timer qlog","description":"cquiche_s_timer qlog id=172ce7b0686cf7d3cd8e9bef4203a68030375ceb","configuration":{"time_offset":0.0}}}
+{"time":0.0,"name":"transport:parameters_set","data":{"owner":"local","tls_cipher":"None","disable_active_migration":false,"max_idle_timeout":30000,"max_udp_payload_size":1200,"ack_delay_exponent":3,"max_ack_delay":25,"active_connection_id_limit":2,"initial_max_data":10000000,"initial_max_stream_data_bidi_local":1000000,"initial_max_stream_data_bidi_remote":1000000,"initial_max_stream_data_uni":1000000,"initial_max_streams_bidi":100,"initial_max_streams_uni":100}}
+{"time":0.05108,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":0,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":0.05108,"frames":[{"frame_type":"crypto","offset":0,"length":1133}]}}
+{"time":0.05108,"name":"recovery:metrics_updated","data":{"smoothed_rtt":333.0,"rtt_variance":166.5,"congestion_window":12000,"bytes_in_flight":1200,"ssthresh":18446744073709551615}}
+{"time":7.533018,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":1,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":7.533018,"frames":[{"frame_type":"crypto","offset":1133,"length":1132}]}}
+{"time":7.533018,"name":"recovery:metrics_updated","data":{"bytes_in_flight":2400}}
+{"time":7.5579987,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":2,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":7.5579987,"frames":[{"frame_type":"crypto","offset":2265,"length":1132}]}}
+{"time":7.5579987,"name":"recovery:metrics_updated","data":{"bytes_in_flight":3600}}
+{"time":7.5664277,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":3,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":7.5664277,"frames":[{"frame_type":"crypto","offset":3397,"length":1132}]}}
+{"time":7.5664277,"name":"recovery:metrics_updated","data":{"bytes_in_flight":4800}}
+{"time":7.573536,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":4,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":7.573536,"frames":[{"frame_type":"crypto","offset":4529,"length":1132}]}}
+{"time":7.573536,"name":"recovery:metrics_updated","data":{"bytes_in_flight":6000}}
+{"time":7.580239,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":5,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":7.580239,"frames":[{"frame_type":"crypto","offset":5661,"length":1132}]}}
+{"time":7.580239,"name":"recovery:metrics_updated","data":{"bytes_in_flight":7200}}
+{"time":7.591206,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":6,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":7.591206,"frames":[{"frame_type":"crypto","offset":6793,"length":1132}]}}
+{"time":7.591206,"name":"recovery:metrics_updated","data":{"bytes_in_flight":8400}}
+{"time":7.597909,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":7,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":7.597909,"frames":[{"frame_type":"crypto","offset":7925,"length":1132}]}}
+{"time":7.597909,"name":"recovery:metrics_updated","data":{"bytes_in_flight":9600}}
+{"time":7.604916,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":8,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":7.604916,"frames":[{"frame_type":"crypto","offset":9057,"length":1132}]}}
+{"time":7.604916,"name":"recovery:metrics_updated","data":{"bytes_in_flight":10800}}
+{"time":7.611313,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":9,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":7.611313,"frames":[{"frame_type":"crypto","offset":10189,"length":1132}]}}
+{"time":7.611313,"name":"recovery:metrics_updated","data":{"bytes_in_flight":12000}}
+{"time":1007.7312,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":10,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":1007.7312,"frames":[{"frame_type":"crypto","offset":0,"length":1133}]}}
+{"time":1007.7312,"name":"recovery:metrics_updated","data":{"bytes_in_flight":13200}}
+{"time":3008.1707,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":11,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":3008.1707,"frames":[{"frame_type":"crypto","offset":0,"length":1133}]}}
+{"time":3008.1707,"name":"recovery:metrics_updated","data":{"bytes_in_flight":14400}}
+{"time":3008.514,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":12,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":3008.514,"frames":[{"frame_type":"crypto","offset":1133,"length":1132}]}}
+{"time":3008.514,"name":"recovery:metrics_updated","data":{"bytes_in_flight":15600}}
+{"time":7008.554,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":13,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":7008.554,"frames":[{"frame_type":"crypto","offset":0,"length":1133}]}}
+{"time":7008.554,"name":"recovery:metrics_updated","data":{"bytes_in_flight":16800}}
+{"time":7009.311,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":14,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":7009.311,"frames":[{"frame_type":"crypto","offset":1133,"length":1132}]}}
+{"time":7009.311,"name":"recovery:metrics_updated","data":{"bytes_in_flight":18000}}
+{"time":15010.692,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":15,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":15010.692,"frames":[{"frame_type":"crypto","offset":0,"length":1133}]}}
+{"time":15010.692,"name":"recovery:metrics_updated","data":{"bytes_in_flight":19200}}
+{"time":15010.9375,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":16,"version":"1","scil":20,"dcil":16,"scid":"172ce7b0686cf7d3cd8e9bef4203a68030375ceb","dcid":"60dbf399c81795d4d4400145aeec37ad"},"raw":{"length":1200,"payload_length":1137},"send_at_time":15010.9375,"frames":[{"frame_type":"crypto","offset":1133,"length":1132}]}}
+{"time":15010.9375,"name":"recovery:metrics_updated","data":{"bytes_in_flight":20400}}
+{"time":30017.871,"name":"connectivity:connection_closed","data":{"owner":"local","reason":"Failed to establish connection","trigger":"handshake_timeout"}}
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 545f5b30515e719d2b280d350e2dcd2df0f819c3..51a91941484104e7d1061f5c9a8a407bbd136465 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
@@ -674,6 +674,33 @@ def transform_cmap_color(
     return r, g, b, a
 
 
+def get_label_for_scenario(label: str) -> str:
+    match label:
+        case "delay":
+            return "Latenz (ms)"
+        case "jitter_delay20ms":
+            return "Jitter (ms)"
+        case "packetloss":
+            return "Paketverlustrate (%)"
+        case "duplicate":
+            return "Duplikationsrate (%)"
+        case "corrupt":
+            return "Korruptierungsrate (%)"
+        case "reorder":
+            return "Neuanordnungsrate (%)"
+        case "rate_both":
+            return "Bandbreite (Mbit/s)"
+        case "rate_client":
+            return "Bandbreite Client (Mbit/s)"
+        case "rate_server":
+            return "Bandbreite Server (Mbit/s)"
+        case "static":
+            return "Nummerierung der Messung"
+        case _:
+            print(f"NO LABEL FOUND FOR {label}", file=sys.stderr)
+            sys.exit(1)
+
+
 # plots lines of different statistical values
 def plot_lines(data):
     def plot_lines_for_sec_level(
@@ -732,8 +759,14 @@ def plot_lines(data):
 
             plt.ylim(bottom=0)
             plt.xlim(left=0, right=x.max() + (x.max() / 50))
-            plt.xlabel(row["scenario"])
-            plt.ylabel(f"Time-to-first-byte (ms)")
+            plt.xlabel(get_label_for_scenario(row["scenario"]))
+            y_label = f"Time-to-first-byte (ms)"
+            if line_type == "iqr":
+                y_label = "Interquartilsabstand (ms)"
+            if line_type == "riqr":
+                y_label = "Interquartilsabstand / Median"
+            plt.ylabel(y_label)
+
             # plt.title(
             #     f"Medians of {row['scenario']} in {row['protocol']} in {row['sec_level']}"
             # )
@@ -814,8 +847,13 @@ def plot_lines(data):
 
             plt.ylim(bottom=0)
             plt.xlim(left=0, right=x.max() + (x.max() / 50))
-            plt.xlabel(row["scenario"])
-            plt.ylabel(f"Time-to-first-byte (ms)")
+            plt.xlabel(get_label_for_scenario(row["scenario"]))
+            y_label = f"Time-to-first-byte (ms)"
+            if line_type == "iqr":
+                y_label = "Interquartilsabstand (ms)"
+            if line_type == "riqr":
+                y_label = "Interquartilsabstand / Median"
+            plt.ylabel(y_label)
             # plt.title(
             #     f"Medians of {row['scenario']} in {row['protocol']} in {row['sec_level']}"
             # )
@@ -874,8 +912,13 @@ def plot_lines(data):
 
             plt.ylim(bottom=0)
             plt.xlim(left=0, right=x.max() + (x.max() / 50))
-            plt.xlabel(row["scenario"])
-            plt.ylabel(f"Time-to-first-byte (ms)")
+            plt.xlabel(get_label_for_scenario(row["scenario"]))
+            y_label = f"Time-to-first-byte (ms)"
+            if line_type == "iqr":
+                y_label = "Interquartilsabstand (ms)"
+            if line_type == "riqr":
+                y_label = "Interquartilsabstand / Median"
+            plt.ylabel(y_label)
             plt.grid()
             plt.legend(
                 bbox_to_anchor=(0.5, 1), loc="lower center", ncol=3, fontsize="small"
@@ -892,6 +935,85 @@ def plot_lines(data):
             )
             plt.close()
 
+    def plot_medians_for_rate_with_cutoff(data, cutoff=5, combined_with_hybrids=False):
+        print("plot_medians_for_rate")
+        os.makedirs(
+            f"{PLOTS_DIR}/lines/medians-rate-with-cutoff/combined-with-hybrids",
+            mode=0o777,
+            exist_ok=True,
+        )
+
+        line_type = "median"
+        for scenario in ["rate_both", "rate_client", "rate_server"]:
+            # get all combination of scenario, protocol, sec_level
+            ldata = data
+            ldata = ldata.query("scenario == @scenario")
+            unique_combinations = ldata[
+                ["scenario", "protocol", "sec_level"]
+            ].drop_duplicates()
+            # print(len(unique_combinations))
+            # print(unique_combinations)
+            for _, row in unique_combinations.iterrows():
+                sec_level = row["sec_level"]
+                if combined_with_hybrids:
+                    sec_level = map_security_level_hybrid_together(row["sec_level"])
+                    if sec_level is None:
+                        continue
+                filtered_data = filter_data(
+                    data,
+                    scenario=scenario,
+                    protocol=row["protocol"],
+                    sec_level=sec_level,
+                )
+                # print(
+                #     f"scenario: {scenario}, protocol: {row['protocol']}, sec_level: {row['sec_level']}"
+                # )
+
+                plt.figure()
+                for idx, kem_alg in enumerate(
+                    filtered_data["kem_alg"].unique().sort_values()
+                ):
+                    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
+                    )
+                    y = filtered_data_single_kem_alg[line_type]
+                    x = get_x_axis(scenario, filtered_data_single_kem_alg, len(y))
+
+                    plt.plot(
+                        x, y, linestyle=mode, marker=".", color=color, label=kem_alg
+                    )
+
+                plt.ylim(bottom=0)
+                plt.xlim(left=0, right=cutoff + 0.2)
+                plt.xlabel(get_label_for_scenario(scenario))
+                plt.ylabel("Time-to-first-byte (ms)")
+
+                plt.xticks(np.arange(0, cutoff + 0.5, 0.5))
+
+                plt.grid()
+                plt.legend(
+                    bbox_to_anchor=(0.5, 1),
+                    loc="lower center",
+                    ncol=3,
+                    fontsize="small",
+                )
+                plt.tight_layout()
+
+                subdir = ""
+                appendix = ""
+                cutoff_str = f"-cutoff-at-{cutoff}"
+                if combined_with_hybrids:
+                    subdir = "combined-with-hybrids/"
+                    appendix = "-combined-with-hybrids"
+                plt.savefig(
+                    f"{PLOTS_DIR}/lines/medians-rate-with-cutoff/{subdir}{line_type}-{scenario}-{row['protocol']}-{row['sec_level']}{cutoff_str}{appendix}.pdf"
+                )
+                plt.close()
+
     def plot_qtls_of_single_algorithm(data):
         print("plot_qtls_of_single_algorithms")
         os.makedirs(
@@ -932,7 +1054,7 @@ def plot_lines(data):
 
             plt.ylim(bottom=0)
             plt.xlim(left=0, right=x.max() + (x.max() / 50))
-            plt.xlabel(row["scenario"])
+            plt.xlabel(get_label_for_scenario(row["scenario"]))
             plt.ylabel(f"Time-to-first-byte (ms)")
             plt.grid()
             plt.legend(
@@ -980,6 +1102,8 @@ def plot_lines(data):
         )
 
     plot_qtls_of_single_algorithm(data)
+    plot_medians_for_rate_with_cutoff(data, cutoff=5, combined_with_hybrids=False)
+    plot_medians_for_rate_with_cutoff(data, cutoff=5, combined_with_hybrids=True)
 
 
 # plots distributions of the individual data points
@@ -1084,7 +1208,7 @@ def plot_distributions(data):
                 plt.ylim(bottom=0, top=1.5 * filtered_data["qtl_95"].max())
                 plt.xticks(tick_values)
             plt.xlim(left=-1.5)
-            plt.xlabel(row["scenario"])
+            plt.xlabel(get_label_for_scenario(row["scenario"]))
             plt.ylabel(f"Time-to-first-byte (ms)")
             plt.grid()
 
diff --git a/pq-tls-benchmark-framework/emulation-exp/code/kex/scripts/queries.py b/pq-tls-benchmark-framework/emulation-exp/code/kex/scripts/queries.py
index 92424b4838434402567a72f610df8275bce900d3..760fa8f2344bcc4ac1e6f3ef19b7841b6d2735e7 100644
--- a/pq-tls-benchmark-framework/emulation-exp/code/kex/scripts/queries.py
+++ b/pq-tls-benchmark-framework/emulation-exp/code/kex/scripts/queries.py
@@ -12,7 +12,8 @@ def main():
     data = pd.read_feather(f"{FEATHERS_DIR}/data.feather")
     # data = pd.read_feather(f"{FEATHERS_DIR}/data_run_20241028.feather")
 
-    loss_calculations()
+    bandwith_calcs()
+    # loss_calculations()
     # static_scenario_statistical_analysis(data)
     # median_of_all_static_runs_per_algorithm(data)
     # stats_of_qtl95_of_packetloss(data)
@@ -23,21 +24,39 @@ def main():
     # print_kem_ids()
 
 
-def loss_calculations():
-    udp_packets_df = pd.read_feather("feathers/udp_packets.feather")
-    df = ap.get_packets_sent_by_node(udp_packets_df)
+def bandwith_calcs():
+    df = get_cic_and_sic()
 
-    print("\n\n Loss calculations")
-    df = df.drop(columns=["length_public_key", "length_ciphertext"])
-    # print(df)
-    df["cic"] = df["client_sent_packets_with_crypto_count"] - 1
-    df["sic"] = df["server_sent_packets_with_crypto_count"]
-    df = df.drop(
-        columns=[
-            "client_sent_packets_with_crypto_count",
-            "server_sent_packets_with_crypto_count",
-        ]
-    )
+    def calc_delay_cuz_of_bandwidth_in_ms(cic, sic, bandwidth, packetlength=1200):
+        """
+        Calculates the delay in ms caused by bandwidth.
+
+        Args:
+            cic: client initial count.
+            sic: server initial count.
+            bandwidth: bandwidth in bits per second.
+            packetlength: length of a packet in bytes.
+
+        Returns:
+            delay in seconds.
+        """
+        SECONDS_IN_MS = 1000
+        return (cic + sic) * packetlength * 8 / bandwidth * SECONDS_IN_MS
+
+    for bw in [0.1, 0.25, 0.5, 1, 3, 5, 500]:
+        df[f"t_delay_{bw}"] = df.apply(
+            lambda row: calc_delay_cuz_of_bandwidth_in_ms(
+                row["cic"], row["sic"], bw * 1000000
+            ),
+            axis=1,
+        )
+
+    print(df)
+    return df
+
+
+def loss_calculations():
+    df = get_cic_and_sic()
 
     # p_noOneSec does not make sense if cic or sic is bigger than 10 -> look thesis
     df = df.query("cic <= 10 and sic <= 10")
@@ -257,4 +276,23 @@ def print_kem_ids():
     print(data)
 
 
-main()
+def get_cic_and_sic():
+    udp_packets_df = pd.read_feather("feathers/udp_packets.feather")
+    df = ap.get_packets_sent_by_node(udp_packets_df)
+
+    print("\n\n Loss calculations")
+    df = df.drop(columns=["length_public_key", "length_ciphertext"])
+    # print(df)
+    df["cic"] = df["client_sent_packets_with_crypto_count"] - 1
+    df["sic"] = df["server_sent_packets_with_crypto_count"]
+    df = df.drop(
+        columns=[
+            "client_sent_packets_with_crypto_count",
+            "server_sent_packets_with_crypto_count",
+        ]
+    )
+    return df
+
+
+if __name__ == "__main__":
+    main()