您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

298 行
10KB

  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. #sns.set(font_scale=1.5)
  13. tex_fonts = {
  14. "pgf.texsystem": "lualatex",
  15. # "legend.fontsize": "x-large",
  16. # "figure.figsize": (15, 5),
  17. "axes.labelsize": 15, # "small",
  18. # "axes.titlesize": "x-large",
  19. "xtick.labelsize": 15, # "small",
  20. "ytick.labelsize": 15, # "small",
  21. "legend.fontsize": 15,
  22. "axes.formatter.use_mathtext": True,
  23. "mathtext.fontset": "dejavusans",
  24. }
  25. # plt.rcParams.update(tex_fonts)
  26. def convert_cellid(value):
  27. if isinstance(value, str):
  28. try:
  29. r = int(value.split(" ")[-1].replace("(", "").replace(")", ""))
  30. return r
  31. except Exception as e:
  32. return -1
  33. else:
  34. return int(-1)
  35. if __name__ == "__main__":
  36. parser = ArgumentParser()
  37. parser.add_argument("-s", "--serial_file", required=True, help="Serial csv file.")
  38. parser.add_argument(
  39. "-p", "--pcap_csv_folder", required=True, help="PCAP csv folder."
  40. )
  41. parser.add_argument("--save", required=True, help="Location to save pdf file.")
  42. parser.add_argument("--fancy", action="store_true", help="Create fancy plot.")
  43. parser.add_argument(
  44. "-i",
  45. "--interval",
  46. default=10,
  47. type=int,
  48. help="Time interval for rolling window.",
  49. )
  50. args = parser.parse_args()
  51. pcap_csv_list = list()
  52. for filename in os.listdir(args.pcap_csv_folder):
  53. if filename.endswith(".csv") and "tcp" in filename:
  54. pcap_csv_list.append(filename)
  55. counter = 1
  56. if len(pcap_csv_list) == 0:
  57. print("No CSV files found.")
  58. pcap_csv_list.sort(key=lambda x: int(x.split("_")[-1].replace(".csv", "")))
  59. for csv in pcap_csv_list:
  60. print(
  61. "\rProcessing {} out of {} CSVs.\t({}%)\t".format(
  62. counter, len(pcap_csv_list), math.floor(counter / len(pcap_csv_list))
  63. )
  64. )
  65. # try:
  66. transmission_df = pd.read_csv(
  67. "{}{}".format(args.pcap_csv_folder, csv),
  68. dtype=dict(is_retranmission=bool, is_dup_ack=bool),
  69. )
  70. transmission_df["datetime"] = pd.to_datetime(
  71. transmission_df["datetime"]
  72. ) - pd.Timedelta(hours=1)
  73. transmission_df = transmission_df.set_index("datetime")
  74. transmission_df.index = pd.to_datetime(transmission_df.index)
  75. transmission_df = transmission_df.sort_index()
  76. # srtt to [s]
  77. transmission_df["srtt"] = transmission_df["srtt"].apply(lambda x: x / 10 ** 6)
  78. # key for columns and level for index
  79. transmission_df["goodput"] = (
  80. transmission_df["payload_size"]
  81. .groupby(pd.Grouper(level="datetime", freq="{}s".format(args.interval)))
  82. .transform("sum")
  83. )
  84. transmission_df["goodput"] = transmission_df["goodput"].apply(
  85. lambda x: ((x * 8) / args.interval) / 10 ** 6
  86. )
  87. transmission_df["goodput_rolling"] = (
  88. transmission_df["payload_size"].rolling("{}s".format(args.interval)).sum()
  89. )
  90. transmission_df["goodput_rolling"] = transmission_df["goodput_rolling"].apply(
  91. lambda x: ((x * 8) / args.interval) / 10 ** 6
  92. )
  93. # set meta values and remove all not needed columns
  94. cc_algo = transmission_df["congestion_control"].iloc[0]
  95. cc_algo = cc_algo.upper()
  96. transmission_direction = transmission_df["direction"].iloc[0]
  97. # transmission_df = transmission_df.filter(["goodput", "datetime", "ack_rtt", "goodput_rolling", "snd_cwnd"])
  98. # read serial csv
  99. serial_df = pd.read_csv(
  100. args.serial_file, converters={"Cell_ID": convert_cellid}
  101. )
  102. serial_df["datetime"] = pd.to_datetime(serial_df["datetime"]) - pd.Timedelta(
  103. hours=1
  104. )
  105. serial_df = serial_df.set_index("datetime")
  106. serial_df.index = pd.to_datetime(serial_df.index)
  107. serial_df.sort_index()
  108. # print(serial_df["Cell_ID"])
  109. # serial_df["Cell_ID"] = serial_df["Cell_ID"].apply(
  110. # lambda x: int(x.split(" ")[-1].replace("(", "").replace(")", "")))
  111. transmission_df = pd.merge_asof(
  112. transmission_df,
  113. serial_df,
  114. tolerance=pd.Timedelta("1ms"),
  115. right_index=True,
  116. left_index=True,
  117. )
  118. transmission_df.index = transmission_df["arrival_time"]
  119. # filter active state
  120. for i in range(1, 5):
  121. transmission_df["LTE_SCC{}_effective_bw".format(i)] = transmission_df[
  122. "LTE_SCC{}_bw".format(i)
  123. ]
  124. mask = transmission_df["LTE_SCC{}_state".format(i)].isin(["ACTIVE"])
  125. transmission_df["LTE_SCC{}_effective_bw".format(i)] = transmission_df[
  126. "LTE_SCC{}_effective_bw".format(i)
  127. ].where(mask, other=0)
  128. # filter if sc is usesd for uplink
  129. for i in range(1, 5):
  130. mask = transmission_df["LTE_SCC{}_UL_Configured".format(i)].isin([False])
  131. transmission_df["LTE_SCC{}_effective_bw".format(i)] = transmission_df[
  132. "LTE_SCC{}_effective_bw".format(i)
  133. ].where(mask, other=0)
  134. # sum all effective bandwidth for 5G and 4G
  135. transmission_df["SCC1_NR5G_effective_bw"] = transmission_df[
  136. "SCC1_NR5G_bw"
  137. ].fillna(0)
  138. transmission_df["lte_effective_bw_sum"] = (
  139. transmission_df["LTE_SCC1_effective_bw"].fillna(0)
  140. + transmission_df["LTE_SCC2_effective_bw"].fillna(0)
  141. + transmission_df["LTE_SCC3_effective_bw"].fillna(0)
  142. + transmission_df["LTE_SCC4_effective_bw"].fillna(0)
  143. + transmission_df["LTE_bw"].fillna(0))
  144. transmission_df["nr_effective_bw_sum"] = transmission_df["SCC1_NR5G_effective_bw"]
  145. transmission_df["effective_bw_sum"] = transmission_df["nr_effective_bw_sum"] + transmission_df[
  146. "lte_effective_bw_sum"]
  147. # transmission timeline
  148. scaley = 1.5
  149. scalex = 1.0
  150. fig, ax = plt.subplots(2, 1, figsize=[6.4 * scaley, 4.8 * scalex])
  151. fig.subplots_adjust(right=0.75)
  152. if not args.fancy:
  153. plt.title("{} with {}".format(transmission_direction, cc_algo))
  154. fig.suptitle("{} with {}".format(transmission_direction, cc_algo))
  155. ax0 = ax[0]
  156. ax1 = ax0.twinx()
  157. ax2 = ax0.twinx()
  158. # ax2.spines.right.set_position(("axes", 1.22))
  159. ax00 = ax[1]
  160. snd_plot = ax0.plot(
  161. transmission_df["snd_cwnd"].dropna(),
  162. color="lime",
  163. linestyle="dashed",
  164. label="cwnd",
  165. )
  166. srtt_plot = ax1.plot(
  167. transmission_df["srtt"].dropna(),
  168. color="red",
  169. linestyle="dashdot",
  170. label="sRTT",
  171. )
  172. goodput_plot = ax2.plot(
  173. transmission_df["goodput_rolling"],
  174. color="blue",
  175. linestyle="solid",
  176. label="goodput",
  177. )
  178. # sum all effective bandwidth for 5G and 4G
  179. transmission_df["SCC1_NR5G_effective_bw"] = transmission_df["SCC1_NR5G_bw"].fillna(0)
  180. transmission_df["effective_bw_sum"] = (
  181. transmission_df["SCC1_NR5G_effective_bw"]
  182. + transmission_df["LTE_SCC1_effective_bw"]
  183. + transmission_df["LTE_SCC2_effective_bw"]
  184. + transmission_df["LTE_SCC3_effective_bw"]
  185. + transmission_df["LTE_SCC4_effective_bw"]
  186. + transmission_df["LTE_bw"]
  187. )
  188. bw_cols = [
  189. "SCC1_NR5G_effective_bw",
  190. "LTE_bw",
  191. "LTE_SCC1_effective_bw",
  192. "LTE_SCC2_effective_bw",
  193. "LTE_SCC3_effective_bw",
  194. "LTE_SCC4_effective_bw",
  195. ]
  196. transmission_df.to_csv("{}{}_plot.csv".format(args.save, csv.replace(".csv", "")))
  197. exit()
  198. ax_stacked = transmission_df[bw_cols].plot.area(stacked=True, linewidth=0, ax=ax00)
  199. ax00.set_ylabel("bandwidth [MHz]")
  200. #ax.set_xlabel("time [minutes]")
  201. #ax00.set_xlim([0, transmission_df.index[-1]])
  202. ax00.xaxis.grid(False)
  203. ax2.spines.right.set_position(("axes", 1.1))
  204. ax0.set_ylim(0, 5000)
  205. ax1.set_ylim(0, 0.3)
  206. ax2.set_ylim(0, 600)
  207. #ax00.set_ylim(-25, 0)
  208. ax00.set_xlabel("arrival time [s]")
  209. ax2.set_ylabel("Goodput [mbps]")
  210. #ax00.set_ylabel("LTE/NR RSRQ [dB]")
  211. # ax02.set_ylabel("LTE RSRQ [dB]")
  212. ax1.set_ylabel("sRTT [s]")
  213. ax0.set_ylabel("cwnd [MSS]")
  214. if args.fancy:
  215. legend_frame = False
  216. ax0.set_xlim([0, transmission_df.index[-1]])
  217. ax00.set_xlim([0, transmission_df.index[-1]])
  218. # added these three lines
  219. lns_ax0 = snd_plot + srtt_plot + goodput_plot
  220. labs_ax0 = [l.get_label() for l in lns_ax0]
  221. ax2.legend(lns_ax0, labs_ax0, ncols=9, fontsize=9, loc="upper right", frameon=legend_frame)
  222. #ax0.set_zorder(100)
  223. #lns_ax00 = [ax_stacked]
  224. #labs_ax00 = ["5G bandwidth", "4G bandwidth"]
  225. #ax00.legend(lns_ax00, labs_ax00, ncols=3, fontsize=9, loc="upper center", frameon=legend_frame)
  226. L = ax00.legend(ncols=3, fontsize=9, frameon=False)
  227. L.get_texts()[0].set_text("5G main")
  228. L.get_texts()[1].set_text("4G main")
  229. L.get_texts()[2].set_text("4G SCC 1")
  230. L.get_texts()[3].set_text("4G SCC 2")
  231. L.get_texts()[4].set_text("4G SCC 3")
  232. L.get_texts()[5].set_text("4G SCC 4")
  233. #ax00.set_zorder(100)
  234. plt.savefig("{}{}_plot.eps".format(args.save, csv.replace(".csv", "")), bbox_inches="tight")
  235. else:
  236. fig.legend(loc="lower right")
  237. plt.savefig("{}{}_plot.pdf".format(args.save, csv.replace(".csv", "")), bbox_inches="tight")
  238. # except Exception as e:
  239. # print("Error processing file: {}".format(csv))
  240. # print(str(e))
  241. counter += 1
  242. plt.close(fig)
  243. plt.clf()