You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 satır
8.1KB

  1. #!/usr/bin/env python3
  2. import math
  3. import multiprocessing
  4. import os
  5. from argparse import ArgumentParser
  6. import matplotlib
  7. import numpy as np
  8. import pandas as pd
  9. import matplotlib.pyplot as plt
  10. # Using seaborn's style
  11. #plt.style.use('seaborn')
  12. tex_fonts = {
  13. "pgf.texsystem": "lualatex",
  14. # "legend.fontsize": "x-large",
  15. # "figure.figsize": (15, 5),
  16. "axes.labelsize": 15, # "small",
  17. # "axes.titlesize": "x-large",
  18. "xtick.labelsize": 15, # "small",
  19. "ytick.labelsize": 15, # "small",
  20. "legend.fontsize": 15,
  21. "axes.formatter.use_mathtext": True,
  22. "mathtext.fontset": "dejavusans",
  23. }
  24. #plt.rcParams.update(tex_fonts)
  25. def convert_cellid(value):
  26. if isinstance(value, str):
  27. return int(value.split(" ")[-1].replace("(", "").replace(")", ""))
  28. else:
  29. return int(-1)
  30. if __name__ == "__main__":
  31. parser = ArgumentParser()
  32. parser.add_argument("-s", "--serial_file", required=True, help="Serial csv file.")
  33. parser.add_argument("-p", "--pcap_csv_folder", required=True, help="PCAP csv folder.")
  34. parser.add_argument("--save", required=True, help="Location to save pdf file.")
  35. parser.add_argument(
  36. "-i",
  37. "--interval",
  38. default=10,
  39. type=int,
  40. help="Time interval for rolling window.",
  41. )
  42. args = parser.parse_args()
  43. pcap_csv_list = list()
  44. for filename in os.listdir(args.pcap_csv_folder):
  45. if filename.endswith(".csv") and "tcp" in filename:
  46. pcap_csv_list.append(filename)
  47. counter = 1
  48. if len(pcap_csv_list) == 0:
  49. print("No CSV files found.")
  50. pcap_csv_list.sort(key=lambda x: int(x.split("_")[-1].replace(".csv", "")))
  51. for csv in pcap_csv_list:
  52. print("\rProcessing {} out of {} CSVs.\t({}%)\t".format(counter, len(pcap_csv_list), math.floor(counter/len(pcap_csv_list))))
  53. #try:
  54. transmission_df = pd.read_csv(
  55. "{}{}".format(args.pcap_csv_folder, csv),
  56. dtype=dict(is_retranmission=bool, is_dup_ack=bool),
  57. )
  58. transmission_df["datetime"] = pd.to_datetime(transmission_df["datetime"]) - pd.Timedelta(hours=1)
  59. transmission_df = transmission_df.set_index("datetime")
  60. transmission_df.index = pd.to_datetime(transmission_df.index)
  61. transmission_df = transmission_df.sort_index()
  62. # srtt to [s]
  63. transmission_df["srtt"] = transmission_df["srtt"].apply(lambda x: x / 10**6)
  64. # key for columns and level for index
  65. transmission_df["goodput"] = transmission_df["payload_size"].groupby(pd.Grouper(level="datetime", freq="{}s".format(args.interval))).transform("sum")
  66. transmission_df["goodput"] = transmission_df["goodput"].apply(
  67. lambda x: ((x * 8) / args.interval) / 10**6
  68. )
  69. transmission_df["goodput_rolling"] = transmission_df["payload_size"].rolling("{}s".format(args.interval)).sum()
  70. transmission_df["goodput_rolling"] = transmission_df["goodput_rolling"].apply(
  71. lambda x: ((x * 8) / args.interval) / 10 ** 6
  72. )
  73. # set meta values and remove all not needed columns
  74. cc_algo = transmission_df["congestion_control"].iloc[0]
  75. cc_algo = cc_algo.upper()
  76. transmission_direction = transmission_df["direction"].iloc[0]
  77. #transmission_df = transmission_df.filter(["goodput", "datetime", "ack_rtt", "goodput_rolling", "snd_cwnd"])
  78. # read serial csv
  79. serial_df = pd.read_csv(args.serial_file, converters={"Cell_ID": convert_cellid})
  80. serial_df["datetime"] = pd.to_datetime(serial_df["datetime"]) - pd.Timedelta(hours=1)
  81. serial_df = serial_df.set_index("datetime")
  82. serial_df.index = pd.to_datetime(serial_df.index)
  83. serial_df.sort_index()
  84. print(serial_df["Cell_ID"])
  85. #serial_df["Cell_ID"] = serial_df["Cell_ID"].apply(
  86. # lambda x: int(x.split(" ")[-1].replace("(", "").replace(")", "")))
  87. transmission_df = pd.merge_asof(
  88. transmission_df,
  89. serial_df,
  90. tolerance=pd.Timedelta("1s"),
  91. right_index=True,
  92. left_index=True,
  93. )
  94. transmission_df.index = transmission_df["arrival_time"]
  95. # replace 0 in RSRQ with Nan
  96. transmission_df["NR5G_RSRQ_(dB)"] = transmission_df["NR5G_RSRQ_(dB)"].replace(0, np.NaN)
  97. transmission_df["RSRQ_(dB)"] = transmission_df["RSRQ_(dB)"].replace(0, np.NaN)
  98. # stacked plot for bandwidth
  99. transmission_df["lte_bw_sum"] = transmission_df["bw_sum"] - transmission_df["NR5G_dl_bw"]
  100. transmission_df["nr_bw_sum"] = transmission_df["NR5G_dl_bw"]
  101. # transmission timeline
  102. scaley = 1.5
  103. scalex = 1.0
  104. plt.title("{} with {}".format(transmission_direction, cc_algo))
  105. fig, ax = plt.subplots(2, 1, figsize=[6.4 * scaley, 4.8 * scalex])
  106. fig.subplots_adjust(right=0.75)
  107. fig.suptitle("{} with {}".format(transmission_direction, cc_algo))
  108. ax0 = ax[0]
  109. ax1 = ax0.twinx()
  110. ax2 = ax0.twinx()
  111. #ax2.spines.right.set_position(("axes", 1.22))
  112. ax00 = ax[1]
  113. ax01 = ax00.twinx()
  114. ax02 = ax00.twinx()
  115. # Plot vertical lines
  116. first = True
  117. lte_handovers = transmission_df["Cell_ID"].dropna().diff()
  118. for index, value in lte_handovers.items():
  119. if value > 0:
  120. if first:
  121. ax00.axvline(index, ymin=0, ymax=1, color="skyblue", label="4G Handover")
  122. first = False
  123. else:
  124. ax00.axvline(index, ymin=0, ymax=1, color="skyblue")
  125. first = True
  126. nr_handovers = transmission_df["NR5G_Cell_ID"].replace(0, np.NaN).dropna().diff()
  127. for index, value in nr_handovers.items():
  128. if value > 0:
  129. if first:
  130. ax00.axvline(index, ymin=0, ymax=1, color="greenyellow", label="5G Handover")
  131. first = False
  132. else:
  133. ax00.axvline(index, ymin=0, ymax=1, color="greenyellow")
  134. ax0.plot(transmission_df["snd_cwnd"].dropna(), color="lime", linestyle="dashed", label="cwnd")
  135. ax1.plot(transmission_df["srtt"].dropna(), color="red", linestyle="dashdot", label="sRTT")
  136. ax2.plot(transmission_df["goodput_rolling"], color="blue", linestyle="solid", label="goodput")
  137. #ax2.plot(transmission_df["goodput"], color="blue", linestyle="solid", label="goodput")
  138. ax01.plot(transmission_df["bw_sum"].dropna(), color="peru", linestyle="solid", label="bandwidth")
  139. ax01.plot(transmission_df["lte_bw_sum"].dropna(), color="lightsteelblue", linestyle="solid", label="4G bandwidth", alpha=.5)
  140. ax01.plot(transmission_df["nr_bw_sum"].dropna(), color="cornflowerblue", linestyle="solid",label="5G bandwidth", alpha=.5)
  141. #ax01.stackplot(transmission_df["arrival_time"].to_list(),
  142. # [transmission_df["lte_bw_sum"].to_list(), transmission_df["nr_bw_sum"].to_list()],
  143. # colors=["lightsteelblue", "cornflowerblue"],
  144. # labels=["4G bandwidth", "5G bandwidth"]
  145. # )
  146. ax02.plot(transmission_df["RSRQ_(dB)"].dropna(), color="purple", linestyle="dotted", label="LTE RSRQ")
  147. ax00.plot(transmission_df["NR5G_RSRQ_(dB)"].dropna(), color="magenta", linestyle="dotted", label="NR RSRQ")
  148. ax2.spines.right.set_position(("axes", 1.1))
  149. ax02.spines.right.set_position(("axes", 1.1))
  150. ax0.set_ylim(0, 5000)
  151. ax1.set_ylim(0, 0.3)
  152. ax2.set_ylim(0, 500)
  153. ax00.set_ylim(-25, 0)
  154. ax01.set_ylim(0, 250)
  155. # second dB axis
  156. ax02.set_ylim(-25, 0)
  157. ax02.set_axis_off()
  158. ax00.set_xlabel("arrival time [s]")
  159. ax2.set_ylabel("Goodput [mbps]")
  160. ax00.set_ylabel("LTE/NR RSRQ [dB]")
  161. #ax02.set_ylabel("LTE RSRQ [dB]")
  162. ax1.set_ylabel("sRTT [s]")
  163. ax0.set_ylabel("cwnd")
  164. ax01.set_ylabel("Bandwidth [MHz]")
  165. fig.legend(loc="lower right")
  166. plt.savefig("{}{}_plot.pdf".format(args.save, csv.replace(".csv", "")))
  167. #except Exception as e:
  168. # print("Error processing file: {}".format(csv))
  169. # print(str(e))
  170. counter += 1
  171. plt.close(fig)
  172. plt.clf()