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