Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/contributed/sumopy/coremodules/misc/matplottools.py
169689 views
1
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
2
# Copyright (C) 2016-2025 German Aerospace Center (DLR) and others.
3
# SUMOPy module
4
# Copyright (C) 2012-2021 University of Bologna - DICAM
5
# This program and the accompanying materials are made available under the
6
# terms of the Eclipse Public License 2.0 which is available at
7
# https://www.eclipse.org/legal/epl-2.0/
8
# This Source Code may also be made available under the following Secondary
9
# Licenses when the conditions for such availability set forth in the Eclipse
10
# Public License 2.0 are satisfied: GNU General Public License, version 2
11
# or later which is available at
12
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
13
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
14
15
# @file matplottools.py
16
# @author Joerg Schweizer
17
# @date 2012
18
19
from agilepy.lib_wx.processdialog import ProcessDialog, ProcessDialogInteractive
20
from agilepy.lib_base.processes import Process
21
from agilepy.lib_base.geometry import *
22
import agilepy.lib_base.arrayman as am
23
import agilepy.lib_base.classman as cm
24
import os
25
import numpy as np
26
from collections import OrderedDict
27
import matplotlib as mpl
28
from matplotlib.patches import Arrow, Circle, Wedge, Polygon, FancyArrow
29
from matplotlib.collections import PatchCollection
30
import matplotlib.colors as colors
31
import matplotlib.cm as cmx
32
import matplotlib.pyplot as plt
33
import matplotlib.image as image
34
from matplotlib.ticker import MaxNLocator
35
import matplotlib.patches as mpatches
36
37
if 0: # change backend...makes problems with plt
38
gui_env = ['WXAgg', 'GTKAgg', 'Qt4Agg', 'TKAgg', ]
39
for gui in gui_env:
40
try:
41
print "Try Matplotlib backend:", gui
42
mpl.use(gui, warn=False, force=True)
43
from mpl.patches import Arrow, Circle, Wedge, Polygon, FancyArrow
44
from mpl.mpl import PatchCollection
45
import matplotlib.colors as colors
46
import mpl.cm as cmx
47
import mpl.pyplot as plt
48
import mpl.image as image
49
from mpl.ticker import MaxNLocator
50
import mpl.patches as mpatches
51
break
52
except:
53
continue
54
print "Using Matplotlib backend", mpl.get_backend()
55
56
57
try:
58
import wx
59
except:
60
print 'WARNING: no wxwindows support'
61
62
63
COLORS = ['#1f77b4', '#aec7e8', '#ff7f0e', '#ffbb78', '#2ca02c',
64
'#98df8a', '#d62728', '#ff9896', '#9467bd', '#c5b0d5',
65
'#8c564b', '#c49c94', '#e377c2', '#f7b6d2', '#7f7f7f',
66
'#c7c7c7', '#bcbd22', '#dbdb8d', '#17becf', '#9edae5']
67
68
LINESTYLES = ['-', '--', '-.', ':', 'None']
69
70
71
MARKERSTYLES = ['None', 'o', 'v', 's', '*', '^', 'h', 'D', 'p', '<', '>']
72
73
global ind_fig
74
ind_fig = 0
75
76
77
def get_color(i):
78
return COLORS[i % len(COLORS)]
79
80
81
def get_colors(inds):
82
return np.array(COLORS, dtype=np.str)[np.mod(inds, len(COLORS))]
83
84
85
def get_marker(i):
86
return MARKERSTYLES[i % len(MARKERSTYLES)]
87
88
89
def get_markers(inds):
90
return np.array(MARKERSTYLES, dtype=np.str)[np.mod(inds, len(MARKERSTYLES))]
91
92
93
class ResultDialog(ProcessDialog):
94
def _get_buttons(self):
95
buttons = [('Plot and close', self.on_run, 'Plot selected quantity in matplotlib window and close this window thereafter.'),
96
('Plot', self.on_show, 'Plot selected quantity in matplotlib window.'),
97
('Save Options...', self.on_save_options, self.on_save_options.__doc__),
98
('Load Options...', self.on_load_options, self.on_load_options.__doc__),
99
]
100
defaultbutton = 'Plot and close'
101
standartbuttons = ['cancel', ]
102
103
return buttons, defaultbutton, standartbuttons
104
105
def on_show(self, event):
106
self.process.show()
107
108
109
def get_mplicon():
110
icondir = os.path.join(os.path.dirname(__file__), 'images')
111
return wx.Bitmap(os.path.join(icondir, 'icon_mpl.png'))
112
113
114
def init_plot(tight_layout=True):
115
plt.close("all")
116
fig = plt.figure()
117
ax = fig.add_subplot(111)
118
if tight_layout:
119
fig.tight_layout()
120
return ax
121
122
123
def init_plot_fig_ax():
124
plt.close("all")
125
fig = plt.figure()
126
ax = fig.add_subplot(111)
127
return fig, ax
128
129
130
def new_plot(tight_layout=True):
131
global ind_fig
132
fig = plt.figure(ind_fig)
133
ind_fig += 1
134
ax = fig.add_subplot(111)
135
if tight_layout:
136
fig.tight_layout()
137
return ax
138
139
140
def new_doubkeplot(tight_layout=True):
141
global ind_fig
142
fig = plt.figure(ind_fig)
143
ind_fig += 1
144
if tight_layout:
145
fig.tight_layout()
146
return plt.subplot(2, 1, 1), plt.subplot(2, 1, 2)
147
148
149
def plot_net(ax, net, color_edge="gray", width_edge=2, color_node=None,
150
alpha=0.5, is_show_connections=True, mapscale=1.0):
151
for shape in net.edges.shapes.get_value():
152
x_vec = np.array(shape)[:, 0]
153
y_vec = np.array(shape)[:, 1]
154
ax.plot(x_vec*mapscale, y_vec*mapscale, color=color_edge, lw=width_edge, alpha=alpha, zorder=-100)
155
if is_show_connections:
156
for id_connection in net.connections.get_ids():
157
x_vec = np.array([net.edges.shapes[net.lanes.ids_edge[net.connections.ids_fromlane[id_connection]]]
158
[-1, 0], net.edges.shapes[net.lanes.ids_edge[net.connections.ids_tolane[id_connection]]][0, 0]])
159
y_vec = np.array([net.edges.shapes[net.lanes.ids_edge[net.connections.ids_fromlane[id_connection]]]
160
[-1, 1], net.edges.shapes[net.lanes.ids_edge[net.connections.ids_tolane[id_connection]]][0, 1]])
161
ax.plot(x_vec*mapscale, y_vec*mapscale, color=color_edge, lw=width_edge*0.8, alpha=alpha, zorder=-100)
162
163
# do nodes
164
if color_node is None:
165
is_nodefill = False
166
color_node = 'none'
167
else:
168
is_nodefill = True
169
170
#ax.scatter(x_vec[0], y_vec[0], s=np.pi * (10.0)**2, c=colors, alpha=0.5)
171
coords = net.nodes.coords.get_value()
172
radii = net.nodes.radii.get_value()
173
#ax.scatter(coords[:,0], coords[:,1], s=np.pi * (radii)**2, alpha=0.5)
174
#patches = []
175
for coord, radius in zip(coords, radii):
176
ax.add_patch(Circle(coord*mapscale, radius=radius*mapscale,
177
linewidth=width_edge,
178
edgecolor=color_edge,
179
facecolor=color_node,
180
fill=is_nodefill,
181
alpha=alpha,
182
zorder=-50))
183
184
185
def plot_maps(ax, maps, alpha=0.5, mapscale=1.0):
186
# print 'plot_maps'
187
net = maps.parent.get_net()
188
rootdir = os.path.dirname(net.parent.get_rootfilepath())
189
190
for filename, bbox in zip(maps.filenames.get_value(), maps.bboxes.get_value()):
191
# print ' ',filename,
192
if filename == os.path.basename(filename):
193
# filename does not contain path info
194
filepath = os.path.join(rootdir, filename)
195
else:
196
# filename contains path info (can happen if interactively inserted)
197
filepath = filename
198
# print ' filepath',filepath
199
im = image.imread(filepath)
200
myaximage = ax.imshow(im, aspect='auto', extent=(
201
bbox[0, 0]*mapscale, bbox[1, 0]*mapscale, bbox[0, 1]*mapscale, bbox[1, 1]*mapscale), alpha=alpha, zorder=-1000)
202
203
# def plot_facilities(ax, facilities, color_building = "gray",
204
# color_outline = 'white', width_line = 2,
205
# alpha = 0.5, mapscale=1.0):
206
207
# if color_building is None:
208
# is_fill = False
209
# color_building = 'none'
210
# else:
211
# is_fill = True
212
# print mpl.patches.Polygon.__doc__
213
# for shape in facilities.shapes.get_value():
214
# #x_vec = np.array(shape)[:,0]
215
# #y_vec = np.array(shape)[:,1]
216
# #ax.plot(x_vec, y_vec, color = color_building, lw = width_line,
217
# # alpha=alpha )
218
# print ' add shape',shape
219
# ax.add_patch(mpl.patches.Polygon( np.array(shape)[:,:2]*mapscale,
220
# linewidth = width_line,
221
# edgecolor = color_outline,
222
# facecolor = color_building,
223
# fill = is_fill,
224
# alpha = alpha,
225
# zorder = -200))
226
227
228
def plot_facilities(ax, facilities, color_building="gray",
229
color_outline='white', width_line=2,
230
alpha=0.5, mapscale=1.0):
231
232
if color_building is None:
233
is_fill = False
234
color_building = 'none'
235
else:
236
is_fill = True
237
for shape in facilities.shapes.get_value():
238
#x_vec = np.array(shape)[:,0]
239
#y_vec = np.array(shape)[:,1]
240
# ax.plot(x_vec, y_vec, color = color_building, lw = width_line,
241
# alpha=alpha )
242
ax.add_patch(mpl.patches.Polygon(np.array(shape)[:, :2]*mapscale,
243
linewidth=width_line,
244
edgecolor=color_outline,
245
facecolor=color_building,
246
fill=is_fill,
247
alpha=alpha,
248
zorder=-200))
249
250
251
def plot_zones(ax, zones, color_zone=None,
252
color_outline='green', width_line=2,
253
alpha=0.5, mapscale=1.0):
254
255
if color_zone is None:
256
is_fill = False
257
color_zone = 'none'
258
else:
259
is_fill = True
260
for shape in zones.shapes.get_value():
261
#x_vec = np.array(shape)[:,0]
262
#y_vec = np.array(shape)[:,1]
263
# ax.plot(x_vec, y_vec, color = color_building, lw = width_line,
264
# alpha=alpha )
265
ax.add_patch(mpl.patches.Polygon(np.array(shape)[:, :2]*mapscale,
266
linewidth=width_line,
267
edgecolor=color_outline,
268
facecolor=color_zone,
269
fill=is_fill,
270
alpha=alpha,
271
zorder=200))
272
273
274
def plot_zone(ax, zone_shape, color_zone="gray",
275
color_outline='white', width_line=2,
276
alpha=0.5, zorder=-200, mapscale=1.0):
277
278
if color_zone is None:
279
is_fill = False
280
color_building = 'none'
281
else:
282
is_fill = True
283
284
shape = (np.array(zone_shape)[:, :2]*mapscale).tolist()
285
print shape
286
ax.add_patch(Polygon(shape,
287
linewidth=width_line,
288
edgecolor=color_outline,
289
facecolor=color_zone,
290
fill=is_fill,
291
alpha=alpha,
292
zorder=-200))
293
294
295
def plot_edgevalues_lines(ax, ids_result=None, config_ids_edge=None, values=[],
296
ids_edge=None, edges=None,
297
width_max=10.0, alpha=0.8, printformat='%.2f',
298
color_outline=None, color_fill=None,
299
color_label='black', is_antialiased=True,
300
is_fill=True, is_widthvalue=True,
301
arrowshape='left', length_arrowhead=10.0,
302
headwidthstretch=1.3,
303
fontsize=32,
304
valuelabel='',
305
value_range=None,
306
is_colorbar=True,
307
mapscale=1.0):
308
# ATTENTION: do not change order of args for backwards compatibility
309
310
head_width = headwidthstretch*width_max
311
fontsize_ticks = int(0.8*fontsize)
312
313
if ids_edge is None:
314
edges = config_ids_edge.get_linktab()
315
ids_edge = config_ids_edge[ids_result]
316
#values = config_values[ids_result]
317
values_norm = np.array(values, dtype=np.float32)/np.max(values)
318
319
patches = []
320
displacement = float(width_max)/2.0
321
if is_widthvalue:
322
linewidths = width_max*values_norm
323
else:
324
linewidths = width_max * np.ones(len(values_norm), np.float32)
325
326
deltaangle_text = -np.pi/2.0
327
displacement_text = displacement+width_max
328
329
jet = cm_jet = plt.get_cmap('jet')
330
if value_range is None:
331
c_norm = colors.Normalize(vmin=0, vmax=np.max(values))
332
else:
333
c_norm = colors.Normalize(vmin=value_range[0], vmax=value_range[1])
334
335
# http://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots/11558629#11558629
336
sm = cmx.ScalarMappable(norm=c_norm, cmap=jet)
337
sm.set_array(values_norm)
338
for id_edge, value, value_norm, linewidth in zip(ids_edge, values, values_norm, linewidths):
339
if not np.isnan(value):
340
shape, angles_perb = get_resultshape(edges, id_edge, displacement)
341
x_vec = np.array(shape)[:, 0]
342
y_vec = np.array(shape)[:, 1]
343
deltax = x_vec[-1]-x_vec[0]
344
deltay = y_vec[-1]-y_vec[0]
345
if is_fill: # means that fill with value proportional color
346
color = sm.to_rgba(value)
347
else:
348
color = color_fill
349
350
# http://matplotlib.org/users/pyplot_tutorial.html
351
line = mpl.lines.Line2D(x_vec*mapscale, y_vec*mapscale, color=color,
352
linewidth=linewidth,
353
antialiased=is_antialiased,
354
alpha=alpha,
355
solid_capstyle='round',
356
zorder=0,
357
)
358
ax.add_line(line)
359
360
if printformat is not '':
361
angles_text = np.arctan2(deltay, deltax)+deltaangle_text
362
# print ' angles_text',printformat%value,angles_text/(np.pi)*180,(angles_text>np.pi/2),(angles_text<3*np.pi/2)
363
if (angles_text > np.pi/2) | (angles_text < -np.pi/2):
364
angles_text += np.pi
365
x_label = x_vec[0]+0.66*deltax+displacement_text*np.cos(angles_text)
366
y_label = y_vec[0]+0.66*deltay+displacement_text*np.sin(angles_text)
367
368
ax.text(x_label*mapscale, y_label*mapscale, printformat % value,
369
rotation=angles_text/(np.pi)*180,
370
color=color_label,
371
fontsize=fontsize_ticks,
372
zorder=10,
373
)
374
375
if is_fill & is_colorbar:
376
cbar = plt.colorbar(sm)
377
# mpl.setp(cbar.ax.yaxis.get_ticklabels(), fontsize=fontsize)#weight='bold',
378
# cb.ax.tick_params(labelsize=font_size)
379
if valuelabel != '':
380
cbar.ax.set_ylabel(valuelabel, fontsize=fontsize) # , weight="bold")
381
for l in cbar.ax.yaxis.get_ticklabels():
382
# l.set_weight("bold")
383
l.set_fontsize(fontsize_ticks)
384
385
386
def plot_connectionvalues_lines(ax, ids_result=None, config_ids_connection=None, values=[],
387
ids_connection=None, connections=None, net=None,
388
width_max=10.0, alpha=0.8, printformat='%.2f',
389
color_outline=None, color_fill=None,
390
color_label='black', is_antialiased=True,
391
is_fill=True, is_widthvalue=True,
392
arrowshape='left', length_arrowhead=10.0,
393
headwidthstretch=1.3,
394
fontsize=32,
395
valuelabel='',
396
value_range=None,
397
is_colorbar=True,
398
mapscale=1.0):
399
# ATTENTION: do not change order of args for backwards compatibility
400
401
head_width = headwidthstretch*width_max
402
fontsize_ticks = int(0.8*fontsize)
403
404
#values = config_values[ids_result]
405
values_norm = np.array(values, dtype=np.float32)/np.max(values)
406
407
patches = []
408
displacement = float(width_max)/2.0
409
if is_widthvalue:
410
linewidths = width_max*values_norm
411
else:
412
linewidths = width_max * np.ones(len(values_norm), np.float32)
413
414
deltaangle_text = -np.pi/2.0
415
displacement_text = displacement+width_max
416
417
jet = cm_jet = plt.get_cmap('jet')
418
if value_range is None:
419
c_norm = colors.Normalize(vmin=0, vmax=np.max(values))
420
else:
421
c_norm = colors.Normalize(vmin=value_range[0], vmax=value_range[1])
422
423
# http://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots/11558629#11558629
424
sm = cmx.ScalarMappable(norm=c_norm, cmap=jet)
425
sm.set_array(values_norm)
426
for id_connection, value, value_norm, linewidth in zip(ids_connection, values, values_norm, linewidths):
427
if not np.isnan(value):
428
shape, angles_perb = get_resultshape_connections(net, id_connection, displacement)
429
x_vec = np.array(shape)[:, 0]
430
y_vec = np.array(shape)[:, 1]
431
deltax = x_vec[-1]-x_vec[0]
432
deltay = y_vec[-1]-y_vec[0]
433
if is_fill: # means that fill with value proportional color
434
color = sm.to_rgba(value)
435
else:
436
color = color_fill
437
438
# http://matplotlib.org/users/pyplot_tutorial.html
439
line = mpl.lines.Line2D(x_vec*mapscale, y_vec*mapscale, color=color,
440
linewidth=linewidth,
441
antialiased=is_antialiased,
442
alpha=alpha,
443
solid_capstyle='round',
444
zorder=0,
445
)
446
ax.add_line(line)
447
448
if printformat is not '':
449
angles_text = np.arctan2(deltay, deltax)+deltaangle_text
450
# print ' angles_text',printformat%value,angles_text/(np.pi)*180,(angles_text>np.pi/2),(angles_text<3*np.pi/2)
451
if (angles_text > np.pi/2) | (angles_text < -np.pi/2):
452
angles_text += np.pi
453
x_label = x_vec[0]+0.66*deltax+displacement_text*np.cos(angles_text)
454
y_label = y_vec[0]+0.66*deltay+displacement_text*np.sin(angles_text)
455
456
ax.text(x_label*mapscale, y_label*mapscale, printformat % value,
457
rotation=angles_text/(np.pi)*180,
458
color=color_label,
459
fontsize=fontsize_ticks,
460
zorder=10,
461
)
462
463
if is_fill & is_colorbar:
464
cbar = plt.colorbar(sm)
465
# mpl.setp(cbar.ax.yaxis.get_ticklabels(), fontsize=fontsize)#weight='bold',
466
# cb.ax.tick_params(labelsize=font_size)
467
if valuelabel != '':
468
cbar.ax.set_ylabel(valuelabel, fontsize=fontsize) # , weight="bold")
469
for l in cbar.ax.yaxis.get_ticklabels():
470
# l.set_weight("bold")
471
l.set_fontsize(fontsize_ticks)
472
473
474
def plot_edgevalues_arrows(ax, ids_result=None, config_ids_edge=None, values=[],
475
ids_edge=None, edges=None,
476
width_max=10.0, alpha=0.8, printformat='%.2f',
477
color_outline=None, color_fill=None,
478
color_label='black', is_antialiased=True,
479
is_fill=True, is_widthvalue=True,
480
arrowshape='left', length_arrowhead=10.0,
481
headwidthstretch=1.3,
482
fontsize=32,
483
valuelabel='',
484
value_range=None,
485
mapscale=1.0):
486
487
# ATTENTION: do not change order of args for backwards compatibility
488
print 'plot_edgevalues_arrows ids_result width_max', width_max
489
# print ' ids_result',ids_result
490
# print ' ids_edge',ids_edge
491
if ids_edge is None:
492
edges = config_ids_edge.get_linktab()
493
ids_edge = config_ids_edge[ids_result]
494
495
head_width = headwidthstretch*width_max
496
fontsize_ticks = int(0.8*fontsize)
497
498
#values = config_values[ids_result]
499
values_norm = np.array(values, dtype=np.float32)/np.max(values)
500
501
patches = []
502
displacement = float(width_max)/4.0
503
if is_widthvalue:
504
linewidths = width_max*values_norm
505
else:
506
linewidths = width_max * np.ones(len(values_norm), np.float32)
507
508
deltaangle_text = -np.pi/2.0
509
displacement_text = displacement+width_max
510
for id_edge, value, value_norm, linewidth in zip(ids_edge, values, values_norm, linewidths):
511
if not np.isnan(value):
512
shape, angles_perb = get_resultshape(edges, id_edge, displacement)
513
x_vec = np.array(shape)[:, 0]
514
y_vec = np.array(shape)[:, 1]
515
deltax = x_vec[-1]-x_vec[0]
516
deltay = y_vec[-1]-y_vec[0]
517
518
if printformat is not '':
519
angles_text = np.arctan2(deltay, deltax)+deltaangle_text
520
if (angles_text > np.pi/2) | (angles_text < -np.pi/2):
521
angles_text += np.pi
522
x_label = x_vec[0]+0.66*deltax+displacement_text*np.cos(angles_text)
523
y_label = y_vec[0]+0.66*deltay+displacement_text*np.sin(angles_text)
524
525
ax.text(x_label*mapscale, y_label*mapscale, printformat % value,
526
rotation=angles_text/(np.pi)*180,
527
color=color_label,
528
fontsize=fontsize_ticks,
529
zorder=10,
530
)
531
532
if is_widthvalue:
533
head_width = headwidthstretch*linewidth
534
arrow = FancyArrow(x_vec[0]*mapscale, y_vec[0]*mapscale, deltax*mapscale, deltay*mapscale, width=linewidth*mapscale,
535
antialiased=is_antialiased,
536
edgecolor=color_outline, facecolor=color_fill,
537
head_width=head_width, head_length=length_arrowhead,
538
length_includes_head=True,
539
fill=True, shape=arrowshape, zorder=0)
540
patches.append(arrow)
541
542
if is_fill:
543
alpha_patch = alpha
544
patchcollection = PatchCollection(patches, cmap=mpl.cm.jet, alpha=alpha_patch)
545
patchcollection.set_array(values)
546
547
# custom value range
548
if value_range is not None:
549
patchcollection.set_clim(value_range)
550
551
ax.add_collection(patchcollection)
552
cbar = plt.colorbar(patchcollection)
553
if valuelabel != '':
554
cbar.ax.set_ylabel(valuelabel, fontsize=fontsize) # , weight="bold")
555
for l in cbar.ax.yaxis.get_ticklabels():
556
# l.set_weight("bold")
557
l.set_fontsize(fontsize_ticks)
558
else:
559
for patch in patches:
560
ax.add_patch(patch)
561
562
563
def plot_connectionvalues_arrows(ax, ids_result=None, config_ids_edge=None, values=[],
564
ids_connection=None, connections=None, net=None,
565
width_max=10.0, alpha=0.8, printformat='%.2f',
566
color_outline=None, color_fill=None,
567
color_label='black', is_antialiased=True,
568
is_fill=True, is_widthvalue=True,
569
arrowshape='left', length_arrowhead=10.0,
570
headwidthstretch=1.3,
571
fontsize=32,
572
valuelabel='',
573
value_range=None,
574
mapscale=1.0):
575
576
# ATTENTION: do not change order of args for backwards compatibility
577
print 'plot_connectionvalues_arrows ids_result'
578
579
head_width = headwidthstretch*width_max
580
fontsize_ticks = int(0.8*fontsize)
581
582
#values = config_values[ids_result]
583
values_norm = np.array(values, dtype=np.float32)/np.max(values)
584
585
patches = []
586
displacement = float(width_max)/4.0
587
if is_widthvalue:
588
linewidths = width_max*values_norm
589
else:
590
linewidths = width_max * np.ones(len(values_norm), np.float32)
591
592
deltaangle_text = -np.pi/2.0
593
displacement_text = displacement+width_max
594
for id_connection, value, value_norm, linewidth in zip(ids_connection, values, values_norm, linewidths):
595
if not np.isnan(value):
596
shape, angles_perb = get_resultshape_connections(net, id_connection, displacement)
597
x_vec = np.array(shape)[:, 0]
598
y_vec = np.array(shape)[:, 1]
599
deltax = x_vec[-1]-x_vec[0]
600
deltay = y_vec[-1]-y_vec[0]
601
602
if printformat is not '':
603
angles_text = np.arctan2(deltay, deltax)+deltaangle_text
604
if (angles_text > np.pi/2) | (angles_text < -np.pi/2):
605
angles_text += np.pi
606
x_label = x_vec[0]+0.66*deltax+displacement_text*np.cos(angles_text)
607
y_label = y_vec[0]+0.66*deltay+displacement_text*np.sin(angles_text)
608
609
ax.text(x_label*mapscale, y_label*mapscale, printformat % value,
610
rotation=angles_text/(np.pi)*180,
611
color=color_label,
612
fontsize=fontsize_ticks,
613
zorder=10,
614
)
615
616
if is_widthvalue:
617
head_width = headwidthstretch*linewidth
618
arrow = FancyArrow(x_vec[0]*mapscale, y_vec[0]*mapscale, deltax*mapscale, deltay*mapscale, width=linewidth*mapscale,
619
antialiased=is_antialiased,
620
edgecolor=color_outline, facecolor=color_fill,
621
head_width=head_width, head_length=length_arrowhead,
622
length_includes_head=True,
623
fill=True, shape=arrowshape, zorder=0)
624
patches.append(arrow)
625
626
if is_fill:
627
alpha_patch = alpha
628
patchcollection = PatchCollection(patches, cmap=mpl.cm.jet, alpha=alpha_patch)
629
patchcollection.set_array(values)
630
631
# custom value range
632
if value_range is not None:
633
patchcollection.set_clim(value_range)
634
635
ax.add_collection(patchcollection)
636
cbar = plt.colorbar(patchcollection)
637
if valuelabel != '':
638
cbar.ax.set_ylabel(valuelabel, fontsize=fontsize) # , weight="bold")
639
for l in cbar.ax.yaxis.get_ticklabels():
640
# l.set_weight("bold")
641
l.set_fontsize(fontsize_ticks)
642
else:
643
for patch in patches:
644
ax.add_patch(patch)
645
646
647
def plot_nodevalues(ax, ids_result=None, config_ids_edge=None, values=[],
648
ids_node=None, nodes=None, net=None,
649
## width_max = 10.0,
650
alpha=0.8,
651
printformat='%.2f',
652
## color_outline = None,
653
## color_fill = None,
654
## color_label = 'black',
655
## is_antialiased = True,
656
is_fill=True,
657
## is_widthvalue = True,
658
## arrowshape = 'left',
659
## length_arrowhead = 10.0,
660
## headwidthstretch = 1.3,
661
fontsize=32,
662
valuelabel='',
663
value_range=None,
664
mapscale=1.0):
665
666
# ATTENTION: do not change order of args for backwards compatibility
667
print 'plot_nodevalues ids_result'
668
fontsize_ticks = int(0.8*fontsize)
669
670
patches = []
671
for id_node, value, in zip(ids_node, values):
672
673
if not np.isnan(value):
674
poly = mpl.patches.Polygon(np.transpose(np.stack((np.array(net.nodes.shapes[id_node])[
675
:][:, 0]*mapscale, np.array(net.nodes.shapes[id_node])[:][:, 1]*mapscale))))
676
patches.append(poly)
677
678
if is_fill:
679
alpha_patch = alpha
680
patchcollection = PatchCollection(patches, cmap=mpl.cm.jet, alpha=alpha_patch)
681
patchcollection.set_array(values)
682
683
# custom value range
684
if value_range is not None:
685
patchcollection.set_clim(value_range)
686
687
ax.add_collection(patchcollection)
688
cbar = plt.colorbar(patchcollection)
689
if valuelabel != '':
690
cbar.ax.set_ylabel(valuelabel, fontsize=fontsize) # , weight="bold")
691
for l in cbar.ax.yaxis.get_ticklabels():
692
# l.set_weight("bold")
693
l.set_fontsize(fontsize_ticks)
694
else:
695
for patch in patches:
696
ax.add_patch(patch)
697
698
699
def plot_pointvalues(ax, x_coords, y_coords, values,
700
net=None,
701
width_max=10.0,
702
alpha=0.8,
703
printformat='%.2f',
704
## color_outline = None,
705
## color_fill = None,
706
## color_label = 'black',
707
## is_antialiased = True,
708
is_fill=True,
709
is_widthvalue=True,
710
## arrowshape = 'left',
711
## length_arrowhead = 10.0,
712
## headwidthstretch = 1.3,
713
fontsize=32,
714
valuelabel='',
715
value_range=None,
716
mapscale=1.0
717
):
718
719
# ATTENTION: do not change order of args for backwards compatibility
720
print 'plot_pointvalues ids_result'
721
fontsize_ticks = int(0.8*fontsize)
722
## i = 0
723
patches = []
724
for x, y, value in zip(x_coords*mapscale, y_coords*mapscale, values):
725
726
if not np.isnan(value):
727
if is_widthvalue:
728
poly = mpl.patches.Circle([x, y], radius=value*width_max/np.max(values)*mapscale, )
729
else:
730
poly = mpl.patches.Circle([x, y], radius=width_max*mapscale)
731
patches.append(poly)
732
# print i
733
# i+=1
734
735
if is_fill:
736
alpha_patch = alpha
737
patchcollection = PatchCollection(patches, cmap=mpl.cm.jet, alpha=alpha_patch)
738
patchcollection.set_array(values)
739
740
# custom value range
741
if value_range is not None:
742
patchcollection.set_clim(value_range)
743
744
ax.add_collection(patchcollection)
745
cbar = plt.colorbar(patchcollection)
746
if valuelabel != '':
747
cbar.ax.set_ylabel(valuelabel, fontsize=fontsize) # , weight="bold")
748
for l in cbar.ax.yaxis.get_ticklabels():
749
# l.set_weight("bold")
750
l.set_fontsize(fontsize_ticks)
751
else:
752
for patch in patches:
753
ax.add_patch(patch)
754
755
756
def get_resultshape(edges, id_edge, dispacement):
757
"""
758
Return resultshape coords for this edge.
759
"""
760
# print 'get_resultshape',edges,'id_edge',id_edge,'dispacement', dispacement
761
shape = np.array(edges.shapes[id_edge], np.float32)
762
n_vert = len(shape)
763
resultshape = np.zeros(shape.shape, np.float32)
764
#laneshapes = np.zeros((n_lanes,n_vert,3), np.float32)
765
angles_perb = get_angles_perpendicular(shape)
766
if edges.types_spread[id_edge] == 0: # right spread
767
768
resultshape[:, 0] = shape[:, 0] + np.cos(angles_perb) * dispacement
769
resultshape[:, 1] = shape[:, 1] + np.sin(angles_perb) * dispacement
770
return resultshape, angles_perb
771
else:
772
return shape.copy(), angles_perb
773
774
775
def get_resultshape_connections(net, id_connection, dispacement):
776
"""
777
Return resultshape coords for this edge.
778
"""
779
print 'get_resultshape', 'connections', 'id_connection', id_connection, 'dispacement', dispacement
780
x0 = net.edges.shapes[net.lanes.ids_edge[net.connections.ids_fromlane[id_connection]]][-1, 0]
781
y0 = net.edges.shapes[net.lanes.ids_edge[net.connections.ids_fromlane[id_connection]]][-1, 1]
782
x1 = net.edges.shapes[net.lanes.ids_edge[net.connections.ids_tolane[id_connection]]][0, 0]
783
y1 = net.edges.shapes[net.lanes.ids_edge[net.connections.ids_tolane[id_connection]]][0, 1]
784
if x0 != x1 or y0 != y1:
785
shape = np.array([[x0, y0, 0.], [x1, y1, 0.]])
786
else:
787
shape = np.array([[x0, y0, 0.], [x1 + 1., y1 + 1., 0.]])
788
print 'connection', id_connection, 'has no shape'
789
n_vert = len(shape)
790
resultshape = np.zeros(shape.shape, np.float32)
791
#laneshapes = np.zeros((n_lanes,n_vert,3), np.float32)
792
angles_perb = get_angles_perpendicular(shape)
793
794
return shape.copy(), angles_perb
795
796
797
def show_plot():
798
plt.show()
799
800
801
class PlotoptionsMixin:
802
803
def add_plotoptions(self, **kwargs):
804
"""
805
[depricated]
806
These are plotoptions for edge results shown on a map.
807
"""
808
attrsman = self.get_attrsman()
809
self.add_edgeresultoptions(**kwargs)
810
self.add_networkoptions(**kwargs)
811
self.add_facilityoptions(**kwargs)
812
self.add_zoneoptions(**kwargs)
813
self.add_plotoptions_mapbase(**kwargs)
814
self.add_plotoptions_base(**kwargs)
815
816
def add_edgeresultoptions(self, **kwargs):
817
attrsman = self.get_attrsman()
818
plottypes = ['arrows', 'polygons']
819
self.plottype = attrsman.add(cm.AttrConf('plottype', kwargs.get('plottype', 'polygons'),
820
choices=plottypes,
821
groupnames=['options'],
822
name='Plot types',
823
info='Plot type representing the results.',
824
))
825
826
self.resultwidth = attrsman.add(cm.AttrConf('resultwidth', kwargs.get('resultwidth', 4.0),
827
groupnames=['options'],
828
name='Result width',
829
unit='m',
830
info='Maximum width of graphical resuls on map.',
831
))
832
833
self.length_arrowhead = attrsman.add(cm.AttrConf('length_arrowhead', kwargs.get('length_arrowhead', 10.0),
834
groupnames=['options'],
835
name='Arrow length',
836
unit='m',
837
info='Length of arrowhead on result map.',
838
))
839
840
self.is_widthvalue = attrsman.add(cm.AttrConf('is_widthvalue', kwargs.get('is_widthvalue', True),
841
groupnames=['options'],
842
name='Value width?',
843
info='If True, the arrow width of the graphical representation is proportional to the result value.',
844
))
845
846
self.is_colorvalue = attrsman.add(cm.AttrConf('is_colorvalue', kwargs.get('is_colorvalue', True),
847
groupnames=['options'],
848
name='Value color?',
849
info='If True, the arrows of the graphical representation are filled with a colour representing the result value.',
850
))
851
852
self.is_value_range = attrsman.add(cm.AttrConf('is_value_range', kwargs.get('is_value_range', False),
853
groupnames=['options'],
854
name='Manual value range?',
855
info='If True, value range is set manually, otherwise value range is adjusted according to values.',
856
))
857
858
self.value_range_min = attrsman.add(cm.AttrConf('value_range_min', kwargs.get('value_range_min', 1.0),
859
groupnames=['options'],
860
name='Min. value range',
861
info='Minimum value range, if manual value range is selected.',
862
))
863
864
self.value_range_max = attrsman.add(cm.AttrConf('value_range_max', kwargs.get('value_range_max', 40.0),
865
groupnames=['options'],
866
name='Max. value range',
867
info='Maximum value range, if manual value range is selected.',
868
))
869
self.color_outline = attrsman.add(cm.AttrConf('color_outline', kwargs.get('color_outline', np.array([0.0, 0.0, 0.0, 0.95], dtype=np.float32)),
870
groupnames=['options'],
871
perm='wr',
872
metatype='color',
873
name='Outline color',
874
info='Outline color of result arrows in graphical representation. Only valid if no color-fill is chosen.',
875
))
876
877
self.color_fill = attrsman.add(cm.AttrConf('color_fill', kwargs.get('color_fill', np.array([0.3, 0.3, 1.0, 0.95], dtype=np.float32)),
878
groupnames=['options'],
879
perm='wr',
880
metatype='color',
881
name='Fill color',
882
info='Fill color of result arrows in graphical representation.',
883
))
884
885
self.valuelabel = attrsman.add(cm.AttrConf('valuelabel', kwargs.get('valuelabel', ''),
886
groupnames=['options'],
887
name='Value label',
888
info='Label of results, as shown in the plot. Leave blank for default values.',
889
))
890
891
self.alpha_results = attrsman.add(cm.AttrConf('alpha_results', kwargs.get('alpha_results', 0.5),
892
groupnames=['options'],
893
name='Result transparency',
894
info='Transparency of result objects in graphical representation.',
895
))
896
897
def add_networkoptions(self, **kwargs):
898
"""
899
Network plot options
900
"""
901
attrsman = self.get_attrsman()
902
self.is_show_network = attrsman.add(cm.AttrConf('is_show_network', kwargs.get('is_show_network', True),
903
groupnames=['options', 'network'],
904
name='Show network',
905
info='Shows a schematic network in the background.',
906
))
907
908
self.is_show_connections = attrsman.add(cm.AttrConf('is_show_connections', kwargs.get('is_show_connections', False),
909
groupnames=['options', 'network'],
910
name='Show network-connections',
911
info='Shows connections between edges in the network.',
912
))
913
914
self.color_network = attrsman.add(cm.AttrConf('color_network', kwargs.get('color_network', np.array([0.8, 0.8, 0.8, 0.8], dtype=np.float32)),
915
groupnames=['options', 'network'],
916
perm='wr',
917
metatype='color',
918
name='Network color',
919
info='Outline color of schematic network in the background.',
920
))
921
922
self.color_nodes = attrsman.add(cm.AttrConf('color_nodes', kwargs.get('color_nodes', np.array([1, 1, 1, 1], dtype=np.float32)),
923
groupnames=['options', 'network'],
924
perm='wr',
925
metatype='color',
926
name='Nodes color',
927
info='Color of simplified nodes (or juctions in the background.',
928
))
929
self.alpha_net = attrsman.add(cm.AttrConf('alpha_net', kwargs.get('alpha_net', 0.5),
930
groupnames=['options', 'network'],
931
name='Net transparency',
932
info='Transparency of network (edges and nodes) in graphical representation.',
933
))
934
self.is_show_maps = attrsman.add(cm.AttrConf('is_show_maps', kwargs.get('is_show_maps', False),
935
groupnames=['options', 'network'],
936
name='Show map?',
937
info='If True, shows map as background in graphical representation. This feature requires that maps have been previously downloaded.',
938
))
939
940
self.alpha_maps = attrsman.add(cm.AttrConf('alpha_maps', kwargs.get('alpha_maps', 0.5),
941
groupnames=['options', 'network'],
942
name='Map transparency',
943
info='Transparency of background maps in graphical representation.',
944
))
945
946
def add_facilityoptions(self, **kwargs):
947
attrsman = self.get_attrsman()
948
self.is_show_facilities = attrsman.add(cm.AttrConf('is_show_facilities', kwargs.get('is_show_facilities', False),
949
groupnames=['options', 'facilities'],
950
name='Show facilities',
951
info='Shows a schematic facilities (buildings, parks, etc.) in the background.',
952
))
953
954
self.color_facilities = attrsman.add(cm.AttrConf('color_facilities', kwargs.get('color_facilities', np.array([1, 1, 1, 1], dtype=np.float32)),
955
groupnames=['options', 'facilities'],
956
perm='wr',
957
metatype='color',
958
name='Facilities color',
959
info='Color of schematic facilities in the background.',
960
))
961
962
self.alpha_facilities = attrsman.add(cm.AttrConf('alpha_facilities', kwargs.get('alpha_facilities', 0.5),
963
groupnames=['options', 'facilities'],
964
name='Facility transparency',
965
info='Transparency of facilities in graphical representation.',
966
))
967
968
self.color_borders = attrsman.add(cm.AttrConf('color_borders', kwargs.get('color_borders', np.array([0.7, 0.7, 0.7, 0.8], dtype=np.float32)),
969
groupnames=['options', 'facilities'],
970
perm='wr',
971
metatype='color',
972
name='Facility border color',
973
info='Facility border (or building walls) color of schematic facilities in the background.',
974
))
975
976
def add_zoneoptions(self, **kwargs):
977
attrsman = self.get_attrsman()
978
self.is_show_zones = attrsman.add(cm.AttrConf('is_show_zones', kwargs.get('is_show_zones', False),
979
groupnames=['options', 'zones'],
980
name='Show Zones',
981
info='Show zone polygons.',
982
))
983
984
self.color_zones = attrsman.add(cm.AttrConf('color_zones', kwargs.get('color_zones', np.array([0.2, 0.8, 0.2, 1.0], dtype=np.float32)),
985
groupnames=['options', 'zones'],
986
perm='wr',
987
metatype='color',
988
name='Zone color',
989
info='Fill color of Zone.',
990
))
991
992
self.alpha_zones = attrsman.add(cm.AttrConf('alpha_zones', kwargs.get('alpha_zones', 0.1),
993
groupnames=['options', 'zones'],
994
name='Zone transparency',
995
info='Transparency of color of zones.',
996
))
997
998
self.color_zoneborders = attrsman.add(cm.AttrConf('color_zoneborders', kwargs.get('color_zoneborders', np.array([0.0, 0.7, 0.0, 1.0], dtype=np.float32)),
999
groupnames=['options', 'zones'],
1000
perm='wr',
1001
metatype='color',
1002
name='Zone border color',
1003
info='Color of zone border.',
1004
))
1005
1006
def add_plotoptions_lineplot(self, is_marker_only=False, **kwargs):
1007
"""
1008
These are plotoptions for y over x oriented graphs.
1009
"""
1010
attrsman = self.get_attrsman()
1011
1012
if not is_marker_only:
1013
self.color_line = attrsman.add(cm.AttrConf('color_line', kwargs.get('color_line', np.array([1, 0, 0, 1], dtype=np.float32)),
1014
groupnames=['options'],
1015
perm='wr',
1016
metatype='color',
1017
name='Line color',
1018
info='Color of line in various diagrams.',
1019
))
1020
1021
self.width_line = attrsman.add(cm.AttrConf('width_line', kwargs.get('width_line', 2),
1022
groupnames=['options'],
1023
perm='wr',
1024
name='Line width',
1025
info='Width of plotted lines.',
1026
))
1027
1028
self.style_line = attrsman.add(cm.AttrConf('style_line', kwargs.get('style_line', '-'),
1029
choices=LINESTYLES,
1030
groupnames=['options'],
1031
name='Line Style',
1032
info='Line styles used for plots.',
1033
))
1034
1035
self.alpha_line = attrsman.add(cm.AttrConf('alpha_line', kwargs.get('alpha_line', 0.9),
1036
groupnames=['options'],
1037
name='Line transparency',
1038
info='Line transparency used for plots.',
1039
))
1040
1041
if is_marker_only:
1042
style_marker_default = 'o'
1043
else:
1044
style_marker_default = 'o'
1045
1046
self.style_marker = attrsman.add(cm.AttrConf('style_marker', kwargs.get('style_marker', style_marker_default),
1047
choices=MARKERSTYLES,
1048
groupnames=['options'],
1049
name='Marker Style',
1050
info='Marker style used for plots.',
1051
))
1052
1053
self.color_marker = attrsman.add(cm.AttrConf('color_marker', kwargs.get('color_marker', np.array([0, 0, 1, 1], dtype=np.float32)),
1054
groupnames=['options'],
1055
perm='wr',
1056
metatype='color',
1057
name='Marker color',
1058
info='Color of marker in plot.',
1059
))
1060
1061
self.size_marker = attrsman.add(cm.AttrConf('size_marker', kwargs.get('size_marker', 16),
1062
groupnames=['options'],
1063
perm='wr',
1064
name='Marker size',
1065
info='Size of marker in plot.',
1066
))
1067
1068
self.xlabel = attrsman.add(cm.AttrConf('xlabel', kwargs.get('xlabel', ''),
1069
groupnames=['options'],
1070
name='X label',
1071
info='X-axis label text, if blank then default values are used.',
1072
))
1073
1074
self.ylabel = attrsman.add(cm.AttrConf('ylabel', kwargs.get('ylabel', ''),
1075
groupnames=['options'],
1076
name='Y label',
1077
info='Y-axis label text, if blank then default values are used.',
1078
))
1079
self.add_plotoptions_base(**kwargs)
1080
1081
def add_plotoptions_mapbase(self, **kwargs):
1082
"""
1083
These are all necessary option to plot whatever on a map.
1084
"""
1085
attrsman = self.get_attrsman()
1086
self.unit_mapscale = attrsman.add(cm.AttrConf('unit_mapscale', kwargs.get('unit_mapscale', 'm'),
1087
groupnames=['options', 'network'],
1088
choices=['m', 'km'],
1089
mapscales={'m': 1.0, 'km': 0.001},
1090
name='Unit',
1091
info='Unit used for map.',
1092
))
1093
1094
def add_plotoptions_base(self, **kwargs):
1095
attrsman = self.get_attrsman()
1096
self.axis = None
1097
self.color_background = attrsman.add(cm.AttrConf('color_background', kwargs.get('color_background', np.array([1, 1, 1, 1], dtype=np.float32)),
1098
groupnames=['options'],
1099
perm='wr',
1100
metatype='color',
1101
name='Background color',
1102
info='Background color of schematic network in the background.',
1103
))
1104
1105
self.is_grid = attrsman.add(cm.AttrConf('is_grid', kwargs.get('is_grid', False),
1106
groupnames=['options'],
1107
name='Show grid?',
1108
info='If True, shows a grid on the graphical representation.',
1109
))
1110
1111
self.is_show_title = attrsman.add(cm.AttrConf('is_show_title', kwargs.get('is_show_title', True),
1112
groupnames=['options'],
1113
name='Show title',
1114
info='Shows title on top of figure.',
1115
))
1116
1117
self.title = attrsman.add(cm.AttrConf('title', kwargs.get('title', ''),
1118
groupnames=['options'],
1119
name='Title',
1120
info='Title text, if blank then default values are used.',
1121
))
1122
1123
self.size_titlefont = attrsman.add(cm.AttrConf('size_titlefont', kwargs.get('size_titlefont', 16),
1124
groupnames=['options'],
1125
name='Title fontsize',
1126
info='Title fontsize.',
1127
))
1128
1129
self.size_labelfont = attrsman.add(cm.AttrConf('size_labelfont', kwargs.get('size_labelfont', 14),
1130
groupnames=['options'],
1131
name='Label fontsize',
1132
info='Label fontsize.',
1133
))
1134
1135
self.printformat = attrsman.add(cm.AttrConf('printformat', kwargs.get('printformat', ''),
1136
choices=OrderedDict([
1137
('Show no values', ''),
1138
('x', '%.d'),
1139
('x.x', '%.1f'),
1140
('x.xx', '%.2f'),
1141
('x.xxx', '%.3f'),
1142
('x.xxxx', '%.4f'),
1143
]),
1144
groupnames=['options'],
1145
name='Label formatting',
1146
info='Print formatting of value label in graphical representation.',
1147
))
1148
1149
self.color_label = attrsman.add(cm.AttrConf('color_label', kwargs.get('color_label', np.array([0, 0, 0, 1], dtype=np.float32)),
1150
groupnames=['options'],
1151
perm='wr',
1152
metatype='color',
1153
name='Label color',
1154
info='Color of value label in graphical representation.',
1155
))
1156
1157
def add_save_options(self, **kwargs):
1158
1159
attrsman = self.get_attrsman()
1160
self.is_save = attrsman.add(cm.AttrConf('is_save', kwargs.get('is_save', False),
1161
groupnames=['options'],
1162
name='Save plots',
1163
info='If true, save plots instead of showing on screen.',
1164
))
1165
1166
self.figformat = attrsman.add(cm.AttrConf('figformat', kwargs.get('figformat', 'png'),
1167
groupnames=['options'],
1168
choices=['png', 'pdf', 'jpg', 'svg'],
1169
name='Graphics format',
1170
info='Format of saved graphic.',
1171
))
1172
self.resolution = attrsman.add(cm.AttrConf('resolution', kwargs.get('resolution', 300),
1173
groupnames=['options'],
1174
name='Resolution',
1175
unit='dpi',
1176
info='Resolution of saved graphic in dots per inch (dpi).',
1177
))
1178
self.figwidth = attrsman.add(cm.AttrConf('figwidth', kwargs.get('figwidth', 40.0),
1179
groupnames=['options'],
1180
name='Figure width',
1181
unit='cm',
1182
info='Figure width.',
1183
))
1184
self.figheight = attrsman.add(cm.AttrConf('figheight', kwargs.get('figheight', 30.0),
1185
groupnames=['options'],
1186
name='Figure height',
1187
unit='cm',
1188
info='Figure height.',
1189
))
1190
1191
def get_scenario(self):
1192
return self.parent.get_scenario()
1193
1194
def init_figures(self):
1195
self._i_fig = 0
1196
plt.close("all")
1197
1198
def create_figure(self):
1199
self._i_fig += 1
1200
fig = plt.figure(self._i_fig,
1201
# dpi=self.resolution,#this may cause huge windows in interactive mode
1202
tight_layout=True,
1203
figsize=(self.figwidth*0.393701, self.figheight*0.393701)
1204
)
1205
return fig
1206
1207
def _autolabel_bars(self, ax, bars, labels):
1208
"""
1209
Helperfunction: Attach a text label above each bar displaying its height
1210
"""
1211
for rect, label in zip(bars, labels):
1212
height = rect.get_height()
1213
if not np.isnan(height):
1214
ax.text(rect.get_x() + rect.get_width()/2., 1.05*height,
1215
'%s' % label,
1216
ha='center', va='bottom',
1217
fontsize=int(0.8*self.size_labelfont),
1218
)
1219
1220
def do(self):
1221
""""This method calls the show method which should be overriden
1222
by to execute class specific plot actions."""
1223
# print 'do',self.edgeattrname
1224
self.show()
1225
return True
1226
1227
def set_figmargins(self):
1228
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)
1229
1230
def save_fig(self, figname):
1231
1232
rootfilepath = self.get_scenario().get_rootfilepath()
1233
filepath = "%s_%s.%s" % (rootfilepath, figname, self.figformat)
1234
print 'save_fig', filepath
1235
plt.savefig(filepath, format=self.figformat,
1236
dpi=self.resolution,
1237
# orientation='landscape',
1238
orientation='portrait',
1239
transparent=True)
1240
1241
def get_edgeresults(self):
1242
"""
1243
Returns table with results which must have the attribute 'ids_edge'
1244
"""
1245
return self.parent.edgeresults
1246
1247
def set_axisborder(self, ax):
1248
ax.spines['top'].set_visible(False)
1249
ax.spines['right'].set_visible(False)
1250
ax.spines['bottom'].set_linewidth(0.5)
1251
ax.spines['left'].set_linewidth(0.5)
1252
1253
def plot_hist(self, ax, x, bins=None, range=None,
1254
color='blue', facecolor=None,
1255
alpha=0.75, label=None,
1256
histtype='step', # {'bar', 'barstacked', 'step', 'stepfilled'}
1257
is_normed=True,
1258
is_cumulative=True,
1259
is_show_mean=True,
1260
is_show_std=False,
1261
is_rel_frequ=False,
1262
is_percent=False,
1263
):
1264
1265
# the histogram of the data
1266
# print 'plot_hist',bins,range
1267
if bins is None:
1268
bins = self.n_bins
1269
1270
if color is None:
1271
color = self.color_line
1272
1273
if is_rel_frequ:
1274
is_cumulative = False
1275
is_normed = False
1276
weights = np.zeros_like(x) + 1. / x.size
1277
else:
1278
weights = np.zeros_like(x) + 1.
1279
1280
if is_percent:
1281
weights *= 100
1282
1283
n, bins0, patches = ax.hist(x, bins, range=range,
1284
normed=is_normed,
1285
cumulative=is_cumulative,
1286
histtype=histtype,
1287
linewidth=self.width_line,
1288
color=color, facecolor=facecolor,
1289
alpha=alpha, label=label,
1290
weights=weights,
1291
)
1292
1293
mean = np.mean(x)
1294
std = np.std(x)
1295
y_min, y_max = ax.get_ylim()
1296
x_min = np.min(x)
1297
x_max = np.max(x)
1298
dy = 0.05*(y_max-y_min)
1299
dx = 0.05*(x_max-x_min)
1300
if is_show_mean:
1301
ax.plot([mean, mean], [y_min, y_max], color=color, linestyle='-.', linewidth=2*self.width_line)
1302
# very good: https://matplotlib.org/users/text_intro.html
1303
# ax.text(3, 8, 'boxed italics text in data coords', style='italic',
1304
# bbox={'facecolor':'red', 'alpha':0.5, 'pad':10})
1305
# ax.annotate(r'$\mu=%.2f$'%mean, xy=(mean, y_max-dy),
1306
# xytext=(mean-dx, y_max-2*dy),
1307
# fontsize=int(0.8*self.size_labelfont),
1308
# arrowprops=dict(facecolor='black', shrink=0.05)
1309
# )
1310
1311
if is_show_std:
1312
ax.plot([mean-std, mean-std], [y_min, y_max], color=color, linestyle='--', linewidth=self.width_line)
1313
ax.plot([mean+std, mean+std], [y_min, y_max], color=color, linestyle='--', linewidth=self.width_line)
1314
1315
# hist uses np.histogram under the hood to create 'n' and 'bins'.
1316
# np.histogram returns the bin edges, so there will be 50 probability
1317
# density values in n, 51 bin edges in bins and 50 patches. To get
1318
# everything lined up, we'll compute the bin centers
1319
bincenters = 0.5*(bins0[1:]+bins0[:-1])
1320
return bincenters
1321
1322
def plot_results_on_map(self, axis, ids_edgeres=None, values=[],
1323
ids_edge=None,
1324
title='', valuelabel='',
1325
is_connection_results=False, ids_connectionres=None, ids_connection=None):
1326
1327
# axis, ids, resultattrconf[ids] , title, valuelabel = resultattrconf.format_symbol()
1328
1329
if self.valuelabel != "":
1330
valuelabel = self.valuelabel
1331
1332
if is_connection_results:
1333
if ids_connection is None:
1334
ids_connection = self.get_connectionresults().ids_connection[ids_connectionres]
1335
else:
1336
if ids_edge is None:
1337
ids_edge = self.get_edgeresults().ids_edge[ids_edgeres]
1338
1339
net = self.get_scenario().net
1340
1341
unit = self.unit_mapscale
1342
mapscale = self.get_attrsman().get_config('unit_mapscale').mapscales[unit]
1343
# print ' unit',unit
1344
# print ' mapscale',mapscale
1345
#xticks =axis.get_xticks()
1346
#yticks =axis.get_yticks()
1347
# print 'xticks',xticks
1348
# print 'yticks',yticks
1349
self.plot_net(axis, mapscale=mapscale, unit=unit, is_configure=False)
1350
1351
if self.is_value_range:
1352
value_range = (self.value_range_min, self.value_range_max)
1353
else:
1354
value_range = None
1355
1356
if is_connection_results:
1357
if self.plottype == 'arrows': # = ['Arrows','Polygons']
1358
plot_connectionvalues_arrows(axis,
1359
# ids,
1360
# edgesresults.ids_edge,
1361
ids_connection=ids_connection,
1362
values=values,
1363
connections=net.connections,
1364
net=net,
1365
width_max=self.resultwidth,
1366
alpha=self.alpha_results,
1367
printformat=self.printformat,
1368
color_outline=self.color_outline,
1369
color_fill=self.color_fill,
1370
color_label=self.color_label,
1371
is_antialiased=True,
1372
is_fill=self.is_colorvalue,
1373
is_widthvalue=self.is_widthvalue,
1374
length_arrowhead=self.length_arrowhead,
1375
fontsize=self.size_labelfont,
1376
valuelabel=valuelabel,
1377
value_range=value_range,
1378
mapscale=mapscale)
1379
elif self.plottype == 'polygons':
1380
plot_connectionvalues_lines(axis,
1381
# ids,
1382
# edgesresults.ids_edge,
1383
ids_connection=ids_connection,
1384
values=values,
1385
connections=net.connections,
1386
net=net,
1387
width_max=self.resultwidth,
1388
alpha=self.alpha_results,
1389
printformat=self.printformat,
1390
color_outline=self.color_outline,
1391
color_fill=self.color_fill,
1392
color_label=self.color_label,
1393
is_antialiased=True,
1394
is_fill=self.is_colorvalue,
1395
is_widthvalue=self.is_widthvalue,
1396
length_arrowhead=self.length_arrowhead,
1397
fontsize=self.size_labelfont,
1398
valuelabel=valuelabel,
1399
value_range=value_range,
1400
mapscale=mapscale)
1401
else:
1402
if len(ids_edge) > 0:
1403
if self.plottype == 'arrows': # = ['Arrows','Polygons']
1404
plot_edgevalues_arrows(axis,
1405
# ids,
1406
# edgesresults.ids_edge,
1407
ids_edge=ids_edge,
1408
values=values,
1409
edges=net.edges,
1410
width_max=self.resultwidth,
1411
alpha=self.alpha_results,
1412
printformat=self.printformat,
1413
color_outline=self.color_outline,
1414
color_fill=self.color_fill,
1415
color_label=self.color_label,
1416
is_antialiased=True,
1417
is_fill=self.is_colorvalue,
1418
is_widthvalue=self.is_widthvalue,
1419
length_arrowhead=self.length_arrowhead,
1420
fontsize=self.size_labelfont,
1421
valuelabel=valuelabel,
1422
value_range=value_range,
1423
mapscale=mapscale)
1424
elif self.plottype == 'polygons':
1425
plot_edgevalues_lines(axis,
1426
# ids,
1427
# edgesresults.ids_edge,
1428
ids_edge=ids_edge,
1429
values=values,
1430
edges=net.edges,
1431
width_max=self.resultwidth,
1432
alpha=self.alpha_results,
1433
printformat=self.printformat,
1434
color_outline=self.color_outline,
1435
color_fill=self.color_fill,
1436
color_label=self.color_label,
1437
is_antialiased=True,
1438
is_fill=self.is_colorvalue,
1439
is_widthvalue=self.is_widthvalue,
1440
length_arrowhead=self.length_arrowhead,
1441
fontsize=self.size_labelfont,
1442
valuelabel=valuelabel,
1443
value_range=value_range,
1444
mapscale=mapscale)
1445
1446
self.configure_map(axis, title, unit=unit)
1447
1448
def configure_map(self, axis, title=None, unit='m'):
1449
1450
if self.is_show_title:
1451
if self.title != "":
1452
title = self.title
1453
1454
axis.set_title(title, fontsize=self.size_titlefont)
1455
1456
axis.axis('equal')
1457
# ax.legend(loc='best',shadow=True)
1458
1459
axis.grid(self.is_grid)
1460
axis.set_xlabel('West-East ['+unit+']', fontsize=self.size_labelfont)
1461
axis.set_ylabel('South-North ['+unit+']', fontsize=self.size_labelfont)
1462
axis.tick_params(axis='x', labelsize=int(0.8*self.size_labelfont))
1463
axis.tick_params(axis='y', labelsize=int(0.8*self.size_labelfont))
1464
1465
# get borders right, this seems to work
1466
plt.subplots_adjust(left=0.12, bottom=0.1, right=0.86, top=0.9, wspace=0.2, hspace=0.2)
1467
1468
# show_plot()
1469
1470
#x_min,y_min,x_max,y_max = net.get_boundaries(is_netboundaries = True)
1471
# axis.set_autoscaley_on(False)
1472
# axis.set_xlim([x_min,x_max])
1473
# axis.set_ylim([y_min,y_max])
1474
1475
def plot_net(self, axis=None, title="", unit='', mapscale=None, is_configure=True):
1476
print 'plot_net mapscale', mapscale
1477
if mapscale is None:
1478
unit = self.unit_mapscale
1479
mapscale = self.get_attrsman().get_config('unit_mapscale').mapscales[unit]
1480
1481
if axis is None:
1482
axis = init_plot()
1483
1484
if hasattr(self, 'is_show_network'):
1485
if self.is_show_network:
1486
net = self.get_scenario().net
1487
plot_net(axis, net, color_edge=self.color_network, width_edge=2,
1488
color_node=self.color_nodes, alpha=self.alpha_net, is_show_connections=self.is_show_connections, mapscale=mapscale)
1489
1490
if hasattr(self, 'is_show_facilities'):
1491
if self.is_show_facilities:
1492
facilities = self.get_scenario().landuse.facilities
1493
plot_facilities(axis, facilities, color_building=self.color_facilities,
1494
color_outline=self.color_borders,
1495
width_line=2, alpha=self.alpha_facilities,
1496
mapscale=mapscale)
1497
if hasattr(self, 'is_show_maps'):
1498
if self.is_show_maps:
1499
plot_maps(axis, self.get_scenario().landuse.maps, alpha=self.alpha_maps, mapscale=mapscale)
1500
1501
if hasattr(self, 'is_show_zones'):
1502
if self.is_show_zones:
1503
zones = self.get_scenario().landuse.zones
1504
plot_zones(axis, zones, color_zone=self.color_zones,
1505
color_outline=self.color_zoneborders,
1506
width_line=2, alpha=self.alpha_zones,
1507
mapscale=mapscale)
1508
if is_configure:
1509
self.configure_map(axis, title=title, unit=unit)
1510
1511
def plot_node_results_on_map(self, axis, ids_noderes=None, values=[],
1512
ids_node=None,
1513
title='', valuelabel='',
1514
is_node_results=False, ):
1515
1516
if ids_node is None:
1517
ids_node = self.get_noderesults().ids_node[ids_noderes]
1518
1519
net = self.get_scenario().net
1520
1521
unit = self.unit_mapscale
1522
mapscale = self.get_attrsman().get_config('unit_mapscale').mapscales[unit]
1523
self.plot_net(axis, mapscale=mapscale, unit=unit, is_configure=False)
1524
1525
if self.is_value_range:
1526
value_range = (self.value_range_min, self.value_range_max)
1527
else:
1528
value_range = None
1529
1530
if is_node_results:
1531
plot_nodevalues(axis,
1532
# ids,
1533
# edgesresults.ids_edge,
1534
ids_node=ids_node,
1535
values=values,
1536
nodes=net.nodes,
1537
## width_max = self.resultwidth,
1538
alpha=self.alpha_results,
1539
## printformat = self.printformat,
1540
## color_outline = self.color_outline,
1541
## color_fill = self.color_fill,
1542
## color_label = self.color_label,
1543
## is_antialiased = True,
1544
is_fill=self.is_colorvalue,
1545
## is_widthvalue = self.is_widthvalue,
1546
## length_arrowhead = self.length_arrowhead,
1547
fontsize=self.size_labelfont,
1548
valuelabel=valuelabel,
1549
value_range=value_range,
1550
net=net
1551
)
1552
1553
self.configure_map(axis, title, unit=unit)
1554
1555
def plot_point_results_on_map(self, net, axis, x_coords, y_coords, values=[],
1556
title='', valuelabel='',
1557
):
1558
1559
unit = self.unit_mapscale
1560
mapscale = self.get_attrsman().get_config('unit_mapscale').mapscales[unit]
1561
self.plot_net(axis, mapscale=mapscale, unit=unit, is_configure=False)
1562
1563
if self.is_value_range:
1564
value_range = (self.value_range_min, self.value_range_max)
1565
else:
1566
value_range = None
1567
1568
plot_pointvalues(axis,
1569
# ids,
1570
# edgesresults.ids_edge,
1571
x_coords=x_coords,
1572
y_coords=y_coords,
1573
values=values,
1574
width_max=self.resultwidth,
1575
alpha=self.alpha_results,
1576
## printformat = self.printformat,
1577
## color_outline = self.color_outline,
1578
## color_fill = self.color_fill,
1579
## color_label = self.color_label,
1580
## is_antialiased = True,
1581
is_fill=self.is_colorvalue,
1582
is_widthvalue=self.is_widthvalue,
1583
## length_arrowhead = self.length_arrowhead,
1584
fontsize=self.size_labelfont,
1585
valuelabel=valuelabel,
1586
value_range=value_range,
1587
net=net
1588
)
1589
1590
self.configure_map(axis, title, unit=unit)
1591
1592