]> rtime.felk.cvut.cz Git - hubacji1/iamcar2.git/blobdiff - scripts/plot.py
Add multiple costs plot function
[hubacji1/iamcar2.git] / scripts / plot.py
index 319886198bb45807efaa794922ed40a844b841cb..f748e79cd437efe63ea6acdb78e778598b582984 100644 (file)
 """Procedures for plotting graphs."""
 import sys
 import matplotlib.pyplot as plt
+import numpy as np
 
 import scenario
 
-def boxplot(w={}, t=""):
+def boxplot(w={}, t="", yl=None, lx="Elapsed time [s]", ly=""):
     """Plot boxplot graph.
 
     Keyword arguments:
     w -- What to plot.
     t -- Graph title.
+    yl -- Y axis limit [min, max].
     """
     f, ax = plt.subplots()
-    ax.set_title(t)
+
+    if False: # is the y axis log scale?
+        ax.set_title("{} -- {} (log yscale)".format(scenario.SNAME, t))
+        ax.set_yscale("log")
+    else:
+        ax.set_title("{} -- {}".format(scenario.SNAME, t))
+
+    ax.set_xlabel(lx)
+    ax.set_ylabel(ly)
+
     ax.boxplot([v for k, v in w.items()], labels=[k for k, v in w.items()])
     ax.minorticks_on()
-    ax.grid(which="major", linestyle="-", linewidth="0.5", color="gray")
-    ax.grid(which="minor", linestyle=":", linewidth="0.5", color="gray")
-    plt.show()
+    ax.grid(
+        which="major",
+        axis="y",
+        linestyle="-",
+        linewidth="0.5",
+        color="gray",
+    )
+    ax.grid(
+        which="minor",
+        axis="y",
+        linestyle=":",
+        linewidth="0.5",
+        color="gray",
+    )
+    if yl:
+        ax.set_ylim(yl)
+    plt.xticks(rotation=45)
+    plt.savefig("out.eps", bbox_inches="tight")
+    plt.close()
+
+def boxplots(w2=[]):
+    """Plot boxplot for multiple times.
+
+    Keyword arguments:
+    w -- What to plot. It is extracted from `w2`.
+    """
+    f, ax = plt.subplots()
+
+    [w, no_opt] = w2
+
+    key = tuple(w.keys())[0]
+    ax.set_title("Final path cost, Out-of-Slot Planner, scenario 5-1".format(key))
+    ax.set_xlabel("Elapsed time [s]")
+    ax.set_ylabel("Cost [m]")
+
+    err_hist = [0 for i in range(19)]
+    val_list = [[] for i in range(19)]
+    m = len(w[key][0])
+    mi = 999999999999
+    ma = -1
+    for i in range(len(w[key])):
+        for j in range(m):
+            if w[key][i][j] == 0:
+                err_hist[j] += 1
+            else:
+                v = w[key][i][j]
+                val_list[j].append(v)
+                if v < mi: mi = v
+                if v > ma: ma = v
+    print("min: {}, max: {}".format(mi, ma))
+
+    maxes = [max(val_list[i]) for i in range(19)]
+    mins = [min(val_list[i]) for i in range(19)]
+    average = [np.average(val_list[i]) for i in range(19)]
+    # 95 and 5 are not used
+    perct_95 = [np.percentile(val_list[i], [95])[0] for i in range(19)]
+    perct_5 = [np.percentile(val_list[i], [5])[0] for i in range(19)]
+    # percentiles by 10 %
+    perct_10 = [np.percentile(val_list[i], [10])[0] for i in range(19)]
+    perct_20 = [np.percentile(val_list[i], [20])[0] for i in range(19)]
+    perct_30 = [np.percentile(val_list[i], [30])[0] for i in range(19)]
+    perct_40 = [np.percentile(val_list[i], [40])[0] for i in range(19)]
+    perct_50 = [np.percentile(val_list[i], [50])[0] for i in range(19)]
+    perct_60 = [np.percentile(val_list[i], [60])[0] for i in range(19)]
+    perct_70 = [np.percentile(val_list[i], [70])[0] for i in range(19)]
+    perct_80 = [np.percentile(val_list[i], [80])[0] for i in range(19)]
+    perct_90 = [np.percentile(val_list[i], [90])[0] for i in range(19)]
+
+    # find index of the closest to average path
+    average_i = [
+        (i, w[key][i][-1])
+        for i in range(len(w[key]))
+    ]
+    average_i = sorted(average_i, key=lambda i: i[1])
+    # this is for figures to the paper
+    print("min: {}".format(average_i[0]))
+    print("max: {}".format(average_i[-1]))
+    print("diff: {}".format(abs(average_i[0][1] - average_i[-1][1])))
+
+    # plot percentiles
+    ax.fill_between(
+        range(1, 20),
+        mins,
+        maxes,
+        color="tab:orange",
+        alpha=0.2,
+        label="Minimum and maximum, optimized",
+    )
+    ax.fill_between(
+        range(1, 20),
+        perct_10,
+        perct_90,
+        color="tab:orange",
+        alpha=0.25,
+        label="10 % and 90 % percentile, optimized",
+    )
+    ax.fill_between(
+        range(1, 20),
+        perct_20,
+        perct_80,
+        color="tab:orange",
+        alpha=0.3,
+        label="20 % and 80 % percentile, optimized",
+    )
+    ax.fill_between(
+        range(1, 20),
+        perct_30,
+        perct_70,
+        color="tab:orange",
+        alpha=0.35,
+        label="30 % and 70 % percentile, optimized",
+    )
+    ax.fill_between(
+        range(1, 20),
+        perct_40,
+        perct_60,
+        color="tab:orange",
+        alpha=0.4,
+        label="40 % and 60 % percentile, optimized",
+    )
+    # plot median and average
+    ax.plot(
+        range(1, 20),
+        perct_50,
+        color="tab:orange",
+        alpha=1,
+        label="50 % percentile (median), optimized",
+    )
+    ax.plot(
+        range(1, 20),
+        average,
+        color="tab:red",
+        alpha=1,
+        label="Average cost after optimization",
+    )
+    # plot average before path optimization
+    ax.plot(
+        range(1, 20),
+        [np.average([i for i in no_opt[key].values()]) for i in range(1, 20)],
+        label="Average cost before optimization",
+        color="tab:blue",
+        linestyle="--",
+    )
+
+    plt.xticks(range(1, 20), ["{:.2f}".format(0.1 * (k+1)) for k in range(m)])
+    ax.minorticks_on()
 
-def barplot(w={}, t=""):
+    plt.rcParams["font.size"] = 21
+    plt.rcParams['hatch.linewidth'] = 1.0
+    plt.rcParams['lines.linewidth'] = 1.0
+    plt.legend()
+    plt.xticks(rotation=45)
+    plt.savefig("out.pdf", bbox_inches="tight")
+    plt.close()
+
+def barplot(wl=[], t="", yl=None, lx="Entry Point Planner variant [-]", ly=""):
     """Plot barplot graph.
 
     Keyword arguments:
-    w -- What to plot.
+    wl -- What to plot list.
     t -- Graph title.
+    yl -- Y axis limit [min, max].
     """
+    if len(wl) < 1:
+        raise ValueError
+    elif len(wl) == 1:
+        wl.append([])
     f, ax = plt.subplots()
     ax.set_title(t)
+    ax.set_xlabel(lx)
+    ax.set_ylabel(ly)
+    w = wl[0]
     ax.bar(
         range(len(w)),
         [v for k, v in w.items()],
         tick_label=[k for k, v in w.items()],
+        width=1 / (len(wl) + 1),
     )
+    for i in range(1, len(wl) - 1):
+        w = wl[i]
+        ax.bar(
+            [j + i * 1/len(wl) for j in range(len(w))],
+            [v for k, v in w.items()],
+            width=1 / (len(wl) + 1),
+        )
     ax.minorticks_on()
-    ax.grid(which="major", linestyle="-", linewidth="0.5", color="gray")
-    ax.grid(which="minor", linestyle=":", linewidth="0.5", color="gray")
-    plt.show()
+    ax.grid(
+        which="major",
+        axis="y",
+        linestyle="-",
+        linewidth="0.5",
+        color="gray"
+    )
+    ax.grid(
+        which="minor",
+        axis="y",
+        linestyle=":",
+        linewidth="0.5",
+        color="gray",
+    )
+    if yl:
+        ax.set_ylim(yl)
+    plt.xticks(rotation=45)
+    plt.savefig("out.eps", bbox_inches="tight")
+    plt.close()
 
-def histplot(w={}, t=""):
+def histplot(w={}, t="", lx="Algorithm computation time [s]", ly="Number of paths found [-]"):
     """Plot histogram graph.
 
     Keyword arguments:
@@ -48,30 +242,91 @@ def histplot(w={}, t=""):
     f, ax = plt.subplots()
     ax.set_title("{} (log yscale)".format(t))
     ax.set_yscale("log")
-    ax.hist([v for k, v in w.items()])
+    ax.set_xlim(-10, 500)
+    ax.set_xlabel(lx)
+    ax.set_ylabel(ly)
+
+    COLORS = ["tab:orange", "tab:red", "tab:blue", "tab:green"]
+    i = 0
+
+    for ck, cv in w.items():
+        ax.hist(
+            [v for k, v in w.items() if k == ck],
+            #alpha = 0.5,
+            histtype = "step",
+            #bins = 30,
+            color=COLORS[i]
+        )
+        X_WHERE = np.percentile([v for k, v in w.items() if k == ck], [95])
+        print("percentile is {}".format(X_WHERE))
+        plt.axvline(X_WHERE, lw=1, linestyle="--", color=COLORS[i])
+        i += 1
+
     ax.minorticks_on()
-    ax.grid(which="major", linestyle="-", linewidth="0.5", color="gray")
-    ax.grid(which="minor", linestyle=":", linewidth="0.5", color="gray")
+    ax.grid(
+        which="major",
+        axis="y",
+        linestyle="-",
+        linewidth="0.5",
+        color="gray",
+    )
+    ax.grid(
+        which="minor",
+        axis="y",
+        linestyle=":",
+        linewidth="0.5",
+        color="gray",
+    )
     plt.legend([k for k, v in w.items()])
-    plt.show()
+    plt.xticks(rotation=45)
+    plt.savefig("out.eps", bbox_inches="tight")
+    plt.close()
 
 if __name__ == "__main__":
     if len(sys.argv) > 1:
         w = sys.argv[1]
     else:
         w = "time"
+    if len(sys.argv) > 2:
+        scenario.DNAME = sys.argv[2]
+
+    plt.rcParams["font.size"] = 22
+    plt.rcParams["font.family"] = "sans-serif"
+    plt.rcParams["figure.figsize"] = [12, 12]
 
     if w == "time":
-        boxplot(scenario.time(), "Elapsed time")
+        boxplot(scenario.time(), "Elapsed time", yl=[0.0004, 200], ly="Time [s]")
     elif w == "htime":
-        histplot(scenario.time(), "Elapsed time histogram")
+        histplot(scenario.time(), "Histogram of time to find a path")
     elif w == "cost":
-        boxplot(scenario.cost(), "Final path cost")
+        boxplot(scenario.cost(), "Final path cost", yl=[0, 80], ly="Cost [m]")
+    elif w == "costs":
+        boxplots(scenario.costs())
     elif w == "hcost":
         histplot(scenario.cost(), "Final path cost histogram")
+    elif w == "orig_cost":
+        boxplot(scenario.orig_cost(), "Original path cost", yl=[0, 80], ly="Cost [m]")
+    elif w == "orig_hcost":
+        histplot(scenario.orig_cost(), "Original path cost histogram")
     elif w == "cusp":
-        boxplot(scenario.cusp(), "Changes in direction")
+        boxplot(scenario.cusp(), "Changes in direction", ly="Changes [-]")
     elif w == "hcusp":
         histplot(scenario.cusp(), "Changes in direction histogram")
     elif w == "error":
-        barplot(scenario.error_rate(), "Error rate")
+        barplot(
+            scenario.error_rate(),
+            "Path not found rate",
+            ly="Path not found [%]",
+        )
+    elif w == "iter":
+        boxplot(
+            scenario.iter(),
+            "Number of iterations",
+            yl=[1, 1000],
+            ly="Iterations [-]",
+        )
+    else:
+        print("""The following arguments are allowed:
+
+        time, htime, cost, hcost, cusp, hcusp, error, iter
+        """)