Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

340 linhas
12KB

  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. import seaborn as sns
  11. sns.set()
  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. try:
  28. r = int(value.split(" ")[-1].replace("(", "").replace(")", ""))
  29. return r
  30. except Exception as e:
  31. return -1
  32. else:
  33. return int(-1)
  34. if __name__ == "__main__":
  35. parser = ArgumentParser()
  36. parser.add_argument("-s", "--serial_file", required=True, help="Serial csv file.")
  37. parser.add_argument(
  38. "-p", "--pcap_csv_folder", required=True, help="PCAP csv folder."
  39. )
  40. parser.add_argument("--save", required=True, help="Location to save pdf file.")
  41. parser.add_argument("--fancy", action="store_true", help="Create fancy plot.")
  42. parser.add_argument(
  43. "-i",
  44. "--interval",
  45. default=10,
  46. type=int,
  47. help="Time interval for rolling window.",
  48. )
  49. args = parser.parse_args()
  50. pcap_csv_list = list()
  51. for filename in os.listdir(args.pcap_csv_folder):
  52. if filename.endswith(".csv") and "tcp" in filename:
  53. pcap_csv_list.append(filename)
  54. counter = 1
  55. if len(pcap_csv_list) == 0:
  56. print("No CSV files found.")
  57. pcap_csv_list.sort(key=lambda x: int(x.split("_")[-1].replace(".csv", "")))
  58. for csv in pcap_csv_list:
  59. print(
  60. "\rProcessing {} out of {} CSVs.\t({}%)\t".format(
  61. counter, len(pcap_csv_list), math.floor(counter / len(pcap_csv_list))
  62. )
  63. )
  64. # try:
  65. transmission_df = pd.read_csv(
  66. "{}{}".format(args.pcap_csv_folder, csv),
  67. dtype=dict(is_retranmission=bool, is_dup_ack=bool),
  68. )
  69. transmission_df["datetime"] = pd.to_datetime(
  70. transmission_df["datetime"]
  71. ) - pd.Timedelta(hours=1)
  72. transmission_df = transmission_df.set_index("datetime")
  73. transmission_df.index = pd.to_datetime(transmission_df.index)
  74. transmission_df = transmission_df.sort_index()
  75. # srtt to [s]
  76. transmission_df["srtt"] = transmission_df["srtt"].apply(lambda x: x / 10 ** 6)
  77. # key for columns and level for index
  78. transmission_df["goodput"] = (
  79. transmission_df["payload_size"]
  80. .groupby(pd.Grouper(level="datetime", freq="{}s".format(args.interval)))
  81. .transform("sum")
  82. )
  83. transmission_df["goodput"] = transmission_df["goodput"].apply(
  84. lambda x: ((x * 8) / args.interval) / 10 ** 6
  85. )
  86. transmission_df["goodput_rolling"] = (
  87. transmission_df["payload_size"].rolling("{}s".format(args.interval)).sum()
  88. )
  89. transmission_df["goodput_rolling"] = transmission_df["goodput_rolling"].apply(
  90. lambda x: ((x * 8) / args.interval) / 10 ** 6
  91. )
  92. # set meta values and remove all not needed columns
  93. cc_algo = transmission_df["congestion_control"].iloc[0]
  94. cc_algo = cc_algo.upper()
  95. transmission_direction = transmission_df["direction"].iloc[0]
  96. # transmission_df = transmission_df.filter(["goodput", "datetime", "ack_rtt", "goodput_rolling", "snd_cwnd"])
  97. # read serial csv
  98. serial_df = pd.read_csv(
  99. args.serial_file, converters={"Cell_ID": convert_cellid}
  100. )
  101. serial_df["datetime"] = pd.to_datetime(serial_df["datetime"]) - pd.Timedelta(
  102. hours=1
  103. )
  104. serial_df = serial_df.set_index("datetime")
  105. serial_df.index = pd.to_datetime(serial_df.index)
  106. serial_df.sort_index()
  107. # print(serial_df["Cell_ID"])
  108. # serial_df["Cell_ID"] = serial_df["Cell_ID"].apply(
  109. # lambda x: int(x.split(" ")[-1].replace("(", "").replace(")", "")))
  110. transmission_df = pd.merge_asof(
  111. transmission_df,
  112. serial_df,
  113. tolerance=pd.Timedelta("1s"),
  114. right_index=True,
  115. left_index=True,
  116. )
  117. transmission_df.index = transmission_df["arrival_time"]
  118. # replace 0 in RSRQ with Nan
  119. transmission_df["NR5G_RSRQ_(dB)"] = transmission_df["NR5G_RSRQ_(dB)"].replace(
  120. 0, np.NaN
  121. )
  122. transmission_df["RSRQ_(dB)"] = transmission_df["RSRQ_(dB)"].replace(0, np.NaN)
  123. # filter active state
  124. for i in range(1, 5):
  125. transmission_df["LTE_SCC{}_effective_bw".format(i)] = transmission_df[
  126. "LTE_SCC{}_bw".format(i)
  127. ]
  128. mask = transmission_df["LTE_SCC{}_state".format(i)].isin(["ACTIVE"])
  129. transmission_df["LTE_SCC{}_effective_bw".format(i)] = transmission_df[
  130. "LTE_SCC{}_effective_bw".format(i)
  131. ].where(mask, other=0)
  132. # filter if sc is usesd for uplink
  133. for i in range(1, 5):
  134. mask = transmission_df["LTE_SCC{}_UL_Configured".format(i)].isin([False])
  135. transmission_df["LTE_SCC{}_effective_bw".format(i)] = transmission_df[
  136. "LTE_SCC{}_effective_bw".format(i)
  137. ].where(mask, other=0)
  138. # sum all effective bandwidth for 5G and 4G
  139. transmission_df["SCC1_NR5G_effective_bw"] = transmission_df[
  140. "SCC1_NR5G_bw"
  141. ].fillna(0)
  142. transmission_df["lte_effective_bw_sum"] = (
  143. transmission_df["LTE_SCC1_effective_bw"].fillna(0)
  144. + transmission_df["LTE_SCC2_effective_bw"].fillna(0)
  145. + transmission_df["LTE_SCC3_effective_bw"].fillna(0)
  146. + transmission_df["LTE_SCC4_effective_bw"].fillna(0)
  147. + transmission_df["LTE_bw"].fillna(0))
  148. transmission_df["nr_effective_bw_sum"] = transmission_df["SCC1_NR5G_effective_bw"]
  149. transmission_df["effective_bw_sum"] = transmission_df["nr_effective_bw_sum"] + transmission_df[
  150. "lte_effective_bw_sum"]
  151. # transmission timeline
  152. scaley = 1.5
  153. scalex = 1.0
  154. fig, ax = plt.subplots(2, 1, figsize=[6.4 * scaley, 4.8 * scalex])
  155. fig.subplots_adjust(right=0.75)
  156. if not args.fancy:
  157. plt.title("{} with {}".format(transmission_direction, cc_algo))
  158. fig.suptitle("{} with {}".format(transmission_direction, cc_algo))
  159. ax0 = ax[0]
  160. ax1 = ax0.twinx()
  161. ax2 = ax0.twinx()
  162. # ax2.spines.right.set_position(("axes", 1.22))
  163. ax00 = ax[1]
  164. ax01 = ax00.twinx()
  165. ax02 = ax00.twinx()
  166. # Plot vertical lines
  167. first = True
  168. lte_handovers = transmission_df["Cell_ID"].dropna().diff()
  169. lte_hanover_plot = None
  170. for index, value in lte_handovers.items():
  171. if value > 0:
  172. if first:
  173. lte_hanover_plot = ax00.axvline(
  174. index, ymin=0, ymax=1, color="skyblue", label="4G Handover"
  175. )
  176. first = False
  177. else:
  178. ax00.axvline(index, ymin=0, ymax=1, color="skyblue")
  179. first = True
  180. nr_handovers = (
  181. transmission_df["NR5G_Cell_ID"].replace(0, np.NaN).dropna().diff()
  182. )
  183. nr_hanover_plot = None
  184. for index, value in nr_handovers.items():
  185. if value > 0:
  186. if first:
  187. nr_hanover_plot = ax00.axvline(
  188. index, ymin=0, ymax=1, color="greenyellow", label="5G Handover"
  189. )
  190. first = False
  191. else:
  192. ax00.axvline(index, ymin=0, ymax=1, color="greenyellow")
  193. snd_plot = ax0.plot(
  194. transmission_df["snd_cwnd"].dropna(),
  195. color="lime",
  196. linestyle="dashed",
  197. label="cwnd",
  198. )
  199. srtt_plot = ax1.plot(
  200. transmission_df["srtt"].dropna(),
  201. color="red",
  202. linestyle="dashdot",
  203. label="sRTT",
  204. )
  205. goodput_plot = ax2.plot(
  206. transmission_df["goodput_rolling"],
  207. color="blue",
  208. linestyle="solid",
  209. label="goodput",
  210. )
  211. # ax2.plot(transmission_df["goodput"], color="blue", linestyle="solid", label="goodput")
  212. eff_bw_plot = ax01.plot(
  213. transmission_df["effective_bw_sum"].dropna(),
  214. color="peru",
  215. linestyle="solid",
  216. label="bandwidth",
  217. )
  218. lte_eff_bw_plot = ax01.plot(
  219. transmission_df["lte_effective_bw_sum"].dropna(),
  220. color="lightsteelblue",
  221. linestyle="solid",
  222. label="4G bandwidth",
  223. alpha=0.5,
  224. )
  225. nr_eff_bw_plot = ax01.plot(
  226. transmission_df["nr_effective_bw_sum"].dropna(),
  227. color="cornflowerblue",
  228. linestyle="solid",
  229. label="5G bandwidth",
  230. alpha=0.5,
  231. )
  232. # ax01.stackplot(transmission_df["arrival_time"].to_list(),
  233. # [transmission_df["lte_bw_sum"].to_list(), transmission_df["nr_bw_sum"].to_list()],
  234. # colors=["lightsteelblue", "cornflowerblue"],
  235. # labels=["4G bandwidth", "5G bandwidth"]
  236. # )
  237. lte_rsrq_plot = ax02.plot(
  238. transmission_df["RSRQ_(dB)"].dropna(),
  239. color="purple",
  240. linestyle="dotted",
  241. label="LTE RSRQ",
  242. )
  243. nr_rsrq_plot = ax00.plot(
  244. transmission_df["NR5G_RSRQ_(dB)"].dropna(),
  245. color="magenta",
  246. linestyle="dotted",
  247. label="NR RSRQ",
  248. )
  249. ax2.spines.right.set_position(("axes", 1.1))
  250. ax02.spines.right.set_position(("axes", 1.1))
  251. ax0.set_ylim(0, 5000)
  252. ax1.set_ylim(0, 0.3)
  253. ax2.set_ylim(0, 500)
  254. ax00.set_ylim(-25, 0)
  255. ax01.set_ylim(0, 250)
  256. # second dB axis
  257. ax02.set_ylim(-25, 0)
  258. ax02.set_axis_off()
  259. ax00.set_xlabel("arrival time [s]")
  260. ax2.set_ylabel("Goodput [mbps]")
  261. ax00.set_ylabel("LTE/NR RSRQ [dB]")
  262. # ax02.set_ylabel("LTE RSRQ [dB]")
  263. ax1.set_ylabel("sRTT [s]")
  264. ax0.set_ylabel("cwnd")
  265. ax01.set_ylabel("Bandwidth [MHz]")
  266. if args.fancy:
  267. ax0.set_xlim([0, transmission_df.index[-1]])
  268. ax00.set_xlim([0, transmission_df.index[-1]])
  269. # added these three lines
  270. lns_ax0 = snd_plot + srtt_plot + goodput_plot
  271. labs_ax0 = [l.get_label() for l in lns_ax0]
  272. ax0.legend(lns_ax0, labs_ax0, ncols=4, fontsize=12, loc="upper center")
  273. lns_ax00 = eff_bw_plot + lte_eff_bw_plot + nr_eff_bw_plot + lte_rsrq_plot + nr_rsrq_plot
  274. if lte_hanover_plot:
  275. lns_ax00.append(lte_hanover_plot)
  276. if nr_hanover_plot:
  277. lns_ax00.append(nr_hanover_plot)
  278. labs_ax00 = [l.get_label() for l in lns_ax00]
  279. ax00.legend(lns_ax00, labs_ax00, ncols=4, fontsize=12, loc="upper center")
  280. plt.savefig("{}{}_plot.eps".format(args.save, csv.replace(".csv", "")), bbox_inches="tight")
  281. else:
  282. fig.legend(loc="lower right")
  283. plt.savefig("{}{}_plot.pdf".format(args.save, csv.replace(".csv", "")), bbox_inches="tight")
  284. # except Exception as e:
  285. # print("Error processing file: {}".format(csv))
  286. # print(str(e))
  287. counter += 1
  288. plt.close(fig)
  289. plt.clf()