]> rtime.felk.cvut.cz Git - hubacji1/iamcar2.git/blob - scripts/plot.py
Fix time-out rate caption
[hubacji1/iamcar2.git] / scripts / plot.py
1 """Procedures for plotting graphs."""
2 import sys
3 import matplotlib.pyplot as plt
4 import numpy as np
5
6 import scenario
7
8 def boxplot(w={}, t="", yl=None, lx="Elapsed time [s]", ly=""):
9     """Plot boxplot graph.
10
11     Keyword arguments:
12     w -- What to plot.
13     t -- Graph title.
14     yl -- Y axis limit [min, max].
15     """
16     f, ax = plt.subplots()
17
18     if False: # is the y axis log scale?
19         ax.set_title("{} -- {} (log yscale)".format(scenario.SNAME, t))
20         ax.set_yscale("log")
21     else:
22         ax.set_title("{} -- {}".format(scenario.SNAME, t))
23
24     ax.set_xlabel(lx)
25     ax.set_ylabel(ly)
26
27     ax.boxplot([v for k, v in w.items()], labels=[k for k, v in w.items()])
28     ax.minorticks_on()
29     ax.grid(
30         which="major",
31         axis="y",
32         linestyle="-",
33         linewidth="0.5",
34         color="gray",
35     )
36     ax.grid(
37         which="minor",
38         axis="y",
39         linestyle=":",
40         linewidth="0.5",
41         color="gray",
42     )
43     if yl:
44         ax.set_ylim(yl)
45     plt.xticks(rotation=45)
46     plt.savefig("out.eps", bbox_inches="tight")
47     plt.close()
48
49 def boxplots(w2=[]):
50     """Plot boxplot for multiple times.
51
52     Keyword arguments:
53     w -- What to plot. It is extracted from `w2`.
54     """
55     f, ax = plt.subplots()
56     eax = ax.twinx()
57
58     [w, no_opt] = w2
59
60     key = tuple(w.keys())[0]
61     title = scenario.TITLE.split("/")[-2].split(".json")[0].split("sc")[1].replace("_", "-")
62     ax.set_title("Final path cost, out-of-slot planner, {}".format(title))
63     ax.set_xlabel("Elapsed time [s]")
64     ax.set_ylabel("Cost [m]")
65     eax.set_ylabel("Timed-out rate [%]")
66
67     M = len(w[key][0])
68     err_hist = [0 for i in range(M)]
69     val_list = [[] for i in range(M)]
70     mi = 999999999999
71     ma = -1
72     N = len(w[key])
73     for i in range(len(w[key])):
74         for j in range(M):
75             if w[key][i][j] == 0:
76                 err_hist[j] += 1
77             else:
78                 v = w[key][i][j]
79                 val_list[j].append(v)
80                 if v < mi: mi = v
81                 if v > ma: ma = v
82     for i in range(len(err_hist)):
83         err_hist[i] *= 100 / N
84
85     maxes = [max(val_list[i]) if len(val_list[i]) > 0 else 0 for i in range(M)]
86     MAX = max(maxes)
87     mins = [min(val_list[i]) if len(val_list[i]) > 0 else 0 for i in range(M)]
88     MIN = min(mins)
89     ax.set_ylim([MIN -5, MAX +5])
90
91     EMAX = max(err_hist)
92     EMIN = 0
93     #eax.set_ylim([-EMAX -5, 0])
94
95     average = [np.average(val_list[i]) for i in range(M)]
96     # 95 and 5 are not used
97     perct_95 = [np.percentile(val_list[i], [95])[0] if len(val_list[i]) > 0 else 0 for i in range(M)]
98     perct_5 = [np.percentile(val_list[i], [5])[0] if len(val_list[i]) > 0 else 0 for i in range(M)]
99     # percentiles by 10 %
100     perct_10 = [np.percentile(val_list[i], [10])[0] if len(val_list[i]) > 0 else 0 for i in range(M)]
101     perct_20 = [np.percentile(val_list[i], [20])[0] if len(val_list[i]) > 0 else 0 for i in range(M)]
102     perct_30 = [np.percentile(val_list[i], [30])[0] if len(val_list[i]) > 0 else 0 for i in range(M)]
103     perct_40 = [np.percentile(val_list[i], [40])[0] if len(val_list[i]) > 0 else 0 for i in range(M)]
104     perct_50 = [np.percentile(val_list[i], [50])[0] if len(val_list[i]) > 0 else 0 for i in range(M)]
105     perct_60 = [np.percentile(val_list[i], [60])[0] if len(val_list[i]) > 0 else 0 for i in range(M)]
106     perct_70 = [np.percentile(val_list[i], [70])[0] if len(val_list[i]) > 0 else 0 for i in range(M)]
107     perct_80 = [np.percentile(val_list[i], [80])[0] if len(val_list[i]) > 0 else 0 for i in range(M)]
108     perct_90 = [np.percentile(val_list[i], [90])[0] if len(val_list[i]) > 0 else 0 for i in range(M)]
109
110     # find index of the closest to average path
111     average_i = [
112         (i, w[key][i][-1])
113         for i in range(len(w[key]))
114     ]
115     average_i = sorted(average_i, key=lambda i: i[1])
116     # this is for figures to the paper -- min/max path cost
117     n0i = 0
118     for i in average_i:
119         if i[1] > 0:
120             n0i = i[0]
121             break
122     print("{} {}".format(n0i, average_i[-1][0]))
123
124     lhs = []
125     # err hist
126     lhs.append(
127     eax.fill_between(
128         range(1, M+1),
129         [i for i in err_hist],
130         [0 for i in range(1, M+1)],
131         color="tab:red",
132         alpha=0.2,
133         label="Not found paths",
134     )
135     )
136     # plot percentiles
137     lhs.append(
138     ax.fill_between(
139         range(1, M+1),
140         mins,
141         maxes,
142         color="tab:orange",
143         alpha=0.2,
144         label="Minimum and maximum, optimized",
145     )
146     )
147     lhs.append(
148     ax.fill_between(
149         range(1, M+1),
150         perct_10,
151         perct_90,
152         color="tab:orange",
153         alpha=0.25,
154         label="10 % and 90 % percentile, optimized",
155     )
156     )
157     lhs.append(
158     ax.fill_between(
159         range(1, M+1),
160         perct_20,
161         perct_80,
162         color="tab:orange",
163         alpha=0.3,
164         label="20 % and 80 % percentile, optimized",
165     )
166     )
167     lhs.append(
168     ax.fill_between(
169         range(1, M+1),
170         perct_30,
171         perct_70,
172         color="tab:orange",
173         alpha=0.35,
174         label="30 % and 70 % percentile, optimized",
175     )
176     )
177     lhs.append(
178     ax.fill_between(
179         range(1, M+1),
180         perct_40,
181         perct_60,
182         color="tab:orange",
183         alpha=0.4,
184         label="40 % and 60 % percentile, optimized",
185     )
186     )
187     # plot median and average
188     lhs.append(
189     ax.plot(
190         range(1, M+1),
191         perct_50,
192         color="tab:orange",
193         alpha=1,
194         label="50 % percentile (median), optimized",
195     )
196     )
197     lhs.append(
198     ax.plot(
199         range(1, M+1),
200         average,
201         color="tab:red",
202         alpha=1,
203         label="Average cost after optimization",
204     )
205     )
206     # plot average before path optimization
207     #ax.plot(
208     #    range(1, M+1),
209     #    [np.average([i for i in no_opt[key].values()]) for i in range(1, M+1)],
210     #    label="Average cost before optimization",
211     #    color="tab:blue",
212     #    linestyle="--",
213     #)
214
215     plt.xticks(range(1, M+1), ["{:.2f}".format(0.1 * (k+1)) for k in range(M)])
216     ax.minorticks_on()
217
218     ax.tick_params(axis='x', labelrotation=45)
219     ax.legend(loc="upper left")
220     eax.legend(loc="upper right")
221     plt.savefig("out.pdf", bbox_inches="tight")
222     plt.close()
223
224 def barplot(wl=[], t="", yl=None, lx="Entry Point Planner variant [-]", ly=""):
225     """Plot barplot graph.
226
227     Keyword arguments:
228     wl -- What to plot list.
229     t -- Graph title.
230     yl -- Y axis limit [min, max].
231     """
232     if len(wl) < 1:
233         raise ValueError
234     elif len(wl) == 1:
235         wl.append([])
236     f, ax = plt.subplots()
237     ax.set_title(t)
238     ax.set_xlabel(lx)
239     ax.set_ylabel(ly)
240     w = wl[0]
241     ax.bar(
242         range(len(w)),
243         [v for k, v in w.items()],
244         tick_label=[k for k, v in w.items()],
245         width=1 / (len(wl) + 1),
246     )
247     for i in range(1, len(wl) - 1):
248         w = wl[i]
249         ax.bar(
250             [j + i * 1/len(wl) for j in range(len(w))],
251             [v for k, v in w.items()],
252             width=1 / (len(wl) + 1),
253         )
254     ax.minorticks_on()
255     ax.grid(
256         which="major",
257         axis="y",
258         linestyle="-",
259         linewidth="0.5",
260         color="gray"
261     )
262     ax.grid(
263         which="minor",
264         axis="y",
265         linestyle=":",
266         linewidth="0.5",
267         color="gray",
268     )
269     if yl:
270         ax.set_ylim(yl)
271     plt.xticks(rotation=45)
272     plt.savefig("out.eps", bbox_inches="tight")
273     plt.close()
274
275 def histplot(w={}, t="", lx="Algorithm computation time [s]", ly="Number of paths found [-]"):
276     """Plot histogram graph.
277
278     Keyword arguments:
279     w -- What to plot.
280     t -- Graph title.
281     """
282     f, ax = plt.subplots()
283     ax.set_title("{} (log yscale)".format(t))
284     ax.set_yscale("log")
285     ax.set_xlim(-10, 500)
286     ax.set_xlabel(lx)
287     ax.set_ylabel(ly)
288
289     COLORS = ["tab:orange", "tab:red", "tab:blue", "tab:green"]
290     i = 0
291
292     for ck, cv in w.items():
293         ax.hist(
294             [v for k, v in w.items() if k == ck],
295             #alpha = 0.5,
296             histtype = "step",
297             #bins = 30,
298             color=COLORS[i]
299         )
300         X_WHERE = np.percentile([v for k, v in w.items() if k == ck], [95])
301         print("percentile is {}".format(X_WHERE))
302         plt.axvline(X_WHERE, lw=1, linestyle="--", color=COLORS[i])
303         i += 1
304
305     ax.minorticks_on()
306     ax.grid(
307         which="major",
308         axis="y",
309         linestyle="-",
310         linewidth="0.5",
311         color="gray",
312     )
313     ax.grid(
314         which="minor",
315         axis="y",
316         linestyle=":",
317         linewidth="0.5",
318         color="gray",
319     )
320     plt.legend([k for k, v in w.items()])
321     plt.xticks(rotation=45)
322     plt.savefig("out.eps", bbox_inches="tight")
323     plt.close()
324
325 if __name__ == "__main__":
326     if len(sys.argv) > 1:
327         w = sys.argv[1]
328     else:
329         w = "time"
330     if len(sys.argv) > 2:
331         scenario.DNAME = sys.argv[2]
332
333     plt.rcParams["figure.figsize"] = [12, 12]
334     plt.rcParams["font.size"] = 21
335     plt.rcParams["font.family"] = "cmr10"
336     plt.rcParams["hatch.linewidth"] = 1.0
337     plt.rcParams["lines.linewidth"] = 1.0
338
339     if w == "time":
340         boxplot(scenario.time(), "Elapsed time", yl=[0.0004, 200], ly="Time [s]")
341     elif w == "htime":
342         histplot(scenario.time(), "Histogram of time to find a path")
343     elif w == "cost":
344         boxplot(scenario.cost(), "Final path cost", yl=[0, 80], ly="Cost [m]")
345     elif w == "costs":
346         boxplots(scenario.costs())
347     elif w == "hcost":
348         histplot(scenario.cost(), "Final path cost histogram")
349     elif w == "orig_cost":
350         boxplot(scenario.orig_cost(), "Original path cost", yl=[0, 80], ly="Cost [m]")
351     elif w == "orig_hcost":
352         histplot(scenario.orig_cost(), "Original path cost histogram")
353     elif w == "cusp":
354         boxplot(scenario.cusp(), "Changes in direction", ly="Changes [-]")
355     elif w == "hcusp":
356         histplot(scenario.cusp(), "Changes in direction histogram")
357     elif w == "error":
358         barplot(
359             scenario.error_rate(),
360             "Path not found rate",
361             ly="Path not found [%]",
362         )
363     elif w == "iter":
364         boxplot(
365             scenario.iter(),
366             "Number of iterations",
367             yl=[1, 1000],
368             ly="Iterations [-]",
369         )
370     else:
371         print("""The following arguments are allowed:
372
373         time, htime, cost, hcost, cusp, hcusp, error, iter
374         """)