sumolib.visualization.helpers
1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 2# Copyright (C) 2013-2026 German Aerospace Center (DLR) and others. 3# This program and the accompanying materials are made available under the 4# terms of the Eclipse Public License 2.0 which is available at 5# https://www.eclipse.org/legal/epl-2.0/ 6# This Source Code may also be made available under the following Secondary 7# Licenses when the conditions for such availability set forth in the Eclipse 8# Public License 2.0 are satisfied: GNU General Public License, version 2 9# or later which is available at 10# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html 11# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later 12 13# @file helpers.py 14# @author Daniel Krajzewicz 15# @author Laura Bieker 16# @author Michael Behrisch 17# @author Mirko Barthauer 18# @date 2013-11-11 19 20from __future__ import absolute_import 21from __future__ import print_function 22 23import gc 24import sys 25 26import matplotlib 27from pylab import arange, close, cm, figure, legend, log, plt, savefig, show, title 28from pylab import xlabel, xlim, xticks, ylabel, ylim, yticks 29from matplotlib.ticker import FuncFormatter as ff 30from matplotlib.collections import LineCollection 31 32from ..options import ArgumentParser 33mpl_version = tuple(map(int, matplotlib.__version__.split(".")[:3])) 34 35if sys.version_info[:2] >= (3, 14): 36 # workaround for https://github.com/matplotlib/matplotlib/issues/29157 37 if mpl_version < (3, 10, 5): 38 import copy # noqa 39 40 def _safe_path_deepcopy(self, memo): 41 # create new instance and deepcopy only attributes (avoid deepcopy(super())) 42 cls = self.__class__ 43 new = cls.__new__(cls) 44 memo[id(self)] = new 45 for k, v in self.__dict__.items(): 46 new.__dict__[k] = copy.deepcopy(v, memo) 47 return new 48 49 matplotlib.path.Path.__deepcopy__ = _safe_path_deepcopy 50 51# http://datadebrief.blogspot.de/2010/10/plotting-sunrise-sunset-times-in-python.html 52 53 54def m2hm0(x, i): 55 h = int(x / 3600) 56 return '%(h)02d' % {'h': h} 57 58 59def m2hm1(x, i): 60 h = int(x / 3600) 61 m = int((x % 3600) / 60) 62 return '%(h)02d:%(m)02d' % {'h': h, 'm': m} 63 64 65def m2hm2(x, i): 66 h = int(x / 3600) 67 m = int((x % 3600) / 60) 68 s = int(x % 60) 69 return '%(h)02d:%(m)02d:%(s)02d' % {'h': h, 'm': m, 's': s} 70 71 72def addPlotOptions(ap): 73 ap.add_argument("--colors", dest="colors", category="visualization", 74 default=None, help="Defines the colors to use") 75 ap.add_argument("--colormap", dest="colormap", category="visualization", 76 default="nipy_spectral", help="Defines the colormap to use") 77 ap.add_argument("--colormap.center", dest="colormapCenter", type=float, category="visualization", 78 help="centers colors at the given value") 79 ap.add_argument("-l", "--labels", dest="labels", category="visualization", 80 default=None, help="Defines the labels to use") 81 ap.add_argument("--xlim", dest="xlim", category="visualization", 82 default=None, help="Defines x-limits of the figure XMIN,XMAX") 83 ap.add_argument("--ylim", dest="ylim", category="visualization", 84 default=None, help="Defines y-limits of the figure YMIN,YMAX") 85 ap.add_argument("--xticks", dest="xticks", category="visualization", 86 default=None, help="Set x-axis ticks XMIN,XMAX,XSTEP,XSIZE or XSIZE") 87 ap.add_argument("--yticks", dest="yticks", category="visualization", 88 default=None, help="Set y-axis ticks YMIN,YMAX,YSTEP,YSIZE or YSIZE") 89 ap.add_argument("--xticks-file", dest="xticksFile", category="input", type=ap.file, 90 default=None, help="Load x-axis ticks from file (LABEL or FLOAT:LABEL per line)") 91 ap.add_argument("--yticks-file", dest="yticksFile", category="input", type=ap.file, 92 default=None, help="Load y-axis ticks from file (LABEL or FLOAT:LABEL per line)") 93 ap.add_argument("--xtime0", dest="xtime0", action="store_true", category="time", 94 default=False, help="Use a time formatter for x-ticks (hh)") 95 ap.add_argument("--ytime0", dest="ytime0", action="store_true", category="time", 96 default=False, help="Use a time formatter for y-ticks (hh)") 97 ap.add_argument("--xtime1", dest="xtime1", action="store_true", category="time", 98 default=False, help="Use a time formatter for x-ticks (hh:mm)") 99 ap.add_argument("--ytime1", dest="ytime1", action="store_true", category="time", 100 default=False, help="Use a time formatter for y-ticks (hh:mm)") 101 ap.add_argument("--xtime2", dest="xtime2", action="store_true", category="time", 102 default=False, help="Use a time formatter for x-ticks (hh:mm:ss)") 103 ap.add_argument("--ytime2", dest="ytime2", action="store_true", category="time", 104 default=False, help="Use a time formatter for y-ticks (hh:mm:ss)") 105 ap.add_argument("--xgrid", dest="xgrid", action="store_true", category="visualization", 106 default=False, help="Enable grid on x-axis") 107 ap.add_argument("--ygrid", dest="ygrid", action="store_true", category="visualization", 108 default=False, help="Enable grid on y-axis") 109 ap.add_argument("--xticksorientation", dest="xticksorientation", category="visualization", 110 type=float, default=None, help="Set the orientation of the x-axis ticks") 111 ap.add_argument("--yticksorientation", dest="yticksorientation", category="visualization", 112 type=float, default=None, help="Set the orientation of the x-axis ticks") 113 ap.add_argument("--xlabel", dest="xlabel", category="visualization", 114 default=None, help="Set the x-axis label") 115 ap.add_argument("--ylabel", dest="ylabel", category="visualization", 116 default=None, help="Set the y-axis label") 117 ap.add_argument("--xlabelsize", dest="xlabelsize", category="visualization", 118 type=int, default=16, help="Set the size of the x-axis label") 119 ap.add_argument("--ylabelsize", dest="ylabelsize", category="visualization", 120 type=int, default=16, help="Set the size of the x-axis label") 121 ap.add_argument("--marker", dest="marker", default=None, category="visualization", 122 help="marker for single points (default o for scatter, None otherwise)") 123 ap.add_argument("--linestyle", dest="linestyle", default="-", category="visualization", 124 help="plot line style (default -)") 125 ap.add_argument("--title", dest="title", category="visualization", 126 default=None, help="Set the title") 127 ap.add_argument("--titlesize", dest="titlesize", category="visualization", 128 type=int, default=16, help="Set the title size") 129 ap.add_argument("--adjust", dest="adjust", category="visualization", 130 default=None, help="Adjust the subplots LEFT,BOTTOM or LEFT,BOTTOM,RIGHT,TOP") 131 ap.add_argument("-s", "--size", dest="size", category="visualization", 132 default=False, help="Defines the figure size X,Y") 133 ap.add_argument("--no-legend", dest="nolegend", action="store_true", category="visualization", 134 default=False, help="Disables the legend") 135 ap.add_argument("--legend-position", dest="legendposition", category="visualization", 136 default=None, help="Sets the legend position") 137 ap.add_argument("--dpi", dest="dpi", type=float, category="visualization", 138 default=None, help="Define dpi resolution for figures") 139 ap.add_argument("--alpha", type=float, 140 default=1., help="Define background transparency of the figure in the range 0..1") 141 142 143def addInteractionOptions(optParser): 144 optParser.add_option("-o", "--output", category="output", dest="output", metavar="FILE", 145 type=ArgumentParser.file_list, 146 default=None, help="Comma separated list of filename(s) the figure shall be written to") 147 optParser.add_option("-b", "--blind", dest="blind", action="store_true", 148 default=False, help="If set, the figure will not be shown") 149 150 151def addNetOptions(optParser): 152 optParser.add_option("-w", "--default-width", dest="defaultWidth", 153 type=float, default=.1, help="Defines the default edge width") 154 optParser.add_option("--default-color", dest="defaultColor", 155 default='k', help="Defines the default edge color") 156 157 158def applyPlotOptions(fig, ax, options): 159 if options.xlim: 160 xlim(float(options.xlim.split(",")[0]), float( 161 options.xlim.split(",")[1])) 162 if options.yticksorientation: 163 ax.tick_params( 164 axis='y', which='major', tickdir=options.xticksorientation) 165 if options.xticks: 166 vals = options.xticks.split(",") 167 if len(vals) == 1: 168 ax.tick_params(axis='x', which='major', labelsize=float(vals[0])) 169 elif len(vals) == 4: 170 xticks(arange(float(vals[0]), float(vals[1]), float(vals[2])), size=float(vals[3])) 171 else: 172 raise ValueError( 173 "Error: ticks must be given as one float (<SIZE>) or four floats (<MIN>,<MAX>,<STEP>,<SIZE>)") 174 if options.xticksFile: 175 xticks(*parseTicks(options.xticksFile)) 176 if options.xtime0: 177 if max(ax.get_xticks()) < 3600: 178 print("Warning: x ticks not suited for hh format.") 179 ax.xaxis.set_major_formatter(ff(m2hm0)) 180 if options.xtime1: 181 if max(ax.get_yticks()) < 60: 182 print("Warning: x ticks not suited for hh:mm format.") 183 ax.xaxis.set_major_formatter(ff(m2hm1)) 184 if options.xtime2: 185 ax.xaxis.set_major_formatter(ff(m2hm2)) 186 if options.xgrid: 187 ax.xaxis.grid(True) 188 if options.xlabel: 189 xlabel(options.xlabel, size=options.xlabelsize) 190 if options.xticksorientation: 191 labels = ax.get_xticklabels() 192 for label in labels: 193 label.set_rotation(options.xticksorientation) 194 195 if options.ylim: 196 ylim(float(options.ylim.split(",")[0]), float( 197 options.ylim.split(",")[1])) 198 if options.yticks: 199 vals = options.yticks.split(",") 200 if len(vals) == 1: 201 ax.tick_params(axis='y', which='major', labelsize=float(vals[0])) 202 elif len(vals) == 4: 203 yticks( 204 arange(float(vals[0]), float(vals[1]), float(vals[2])), size=float(vals[3])) 205 else: 206 raise ValueError( 207 "Error: ticks must be given as one float (<SIZE>) or four floats (<MIN>,<MAX>,<STEP>,<SIZE>)") 208 if options.yticksFile: 209 yticks(*parseTicks(options.yticksFile)) 210 if options.ytime0: 211 if max(ax.get_yticks()) < 3600: 212 print("Warning: y ticks not suited for hh format.") 213 ax.yaxis.set_major_formatter(ff(m2hm0)) 214 if options.ytime1: 215 if max(ax.get_yticks()) < 60: 216 print("Warning: y ticks not suited for hh:mm format.") 217 ax.yaxis.set_major_formatter(ff(m2hm1)) 218 if options.ytime2: 219 ax.yaxis.set_major_formatter(ff(m2hm2)) 220 if options.ygrid: 221 ax.yaxis.grid(True) 222 if options.ylabel: 223 ylabel(options.ylabel, size=options.ylabelsize) 224 if options.yticksorientation: 225 labels = ax.get_yticklabels() 226 for label in labels: 227 label.set_rotation(options.yticksorientation) 228 229 if options.title: 230 title(options.title, size=options.titlesize) 231 if options.adjust: 232 vals = options.adjust.split(",") 233 if len(vals) == 2: 234 fig.subplots_adjust(left=float(vals[0]), bottom=float(vals[1])) 235 elif len(vals) == 4: 236 fig.subplots_adjust(left=float(vals[0]), bottom=float( 237 vals[1]), right=float(vals[2]), top=float(vals[3])) 238 else: 239 raise ValueError( 240 "Error: adjust must be given as two floats (<LEFT>,<BOTTOM>) or four floats " + 241 "(<LEFT>,<BOTTOM>,<RIGHT>,<TOP>)") 242 if options.alpha is not None: 243 alpha = max(0., min(1., options.alpha)) 244 fig.patch.set_alpha(alpha) 245 ax.patch.set_alpha(alpha) 246 247 248def plotNet(net, colors, widths, options): 249 shapes = [] 250 c = [] 251 w = [] 252 for e in net._edges: 253 shapes.append(e.getShape()) 254 if e._id in colors: 255 c.append(colors[str(e._id)]) 256 else: 257 c.append(options.defaultColor) 258 if e._id in widths: 259 w.append(widths[str(e._id)]) 260 else: 261 w.append(options.defaultWidth) 262 263 line_segments = LineCollection(shapes, linewidths=w, colors=c, linestyles=options.linestyle) 264 ax = plt.gca() 265 ax.add_collection(line_segments) 266 ax.set_xmargin(0.1) 267 ax.set_ymargin(0.1) 268 ax.autoscale_view(True, True, True) 269 270 271def getColorMap(options): 272 if mpl_version < (3, 6, 0): 273 return matplotlib.cm.get_cmap(options.colormap) 274 return matplotlib.colormaps[options.colormap] 275 276 277def getColor(options, i, a): 278 if options.colors: 279 v = options.colors.split(",") 280 if i >= len(v): 281 raise ValueError("Error: not enough colors given") 282 return v[i] 283 if options.colormap[0] == '#': 284 colormap = parseColorMap(options.colormap[1:]) 285 if mpl_version < (3, 6, 0): 286 cm.register_cmap(name="CUSTOM", cmap=colormap) 287 else: 288 matplotlib.colormaps.register(name="CUSTOM", cmap=colormap) 289 options.colormap = "CUSTOM" 290 if options.colormapCenter: 291 cNorm = matplotlib.colors.TwoSlopeNorm(vmin=0, vcenter=options.colormapCenter, vmax=a) 292 else: 293 cNorm = matplotlib.colors.Normalize(vmin=0, vmax=a) 294 scalarMap = matplotlib.cm.ScalarMappable(norm=cNorm, cmap=getColorMap(options)) 295 return scalarMap.to_rgba(i) 296 297 298def getLabel(f, i, options): 299 label = f 300 if options.labels: 301 label = options.labels.split(",")[i] 302 return label 303 304 305def openFigure(options): 306 if options.size: 307 x = float(options.size.split(",")[0]) 308 y = float(options.size.split(",")[1]) 309 fig = figure(figsize=(x, y)) 310 else: 311 fig = figure() 312 ax = fig.add_subplot(111) 313 return fig, ax 314 315 316def closeFigure(fig, ax, options, haveLabels=True, optOut=None): 317 if haveLabels and not options.nolegend: 318 if options.legendposition: 319 legend(loc=options.legendposition) 320 else: 321 legend() 322 applyPlotOptions(fig, ax, options) 323 if options.output or optOut is not None: 324 n = options.output 325 myDpi = options.dpi 326 if myDpi is not None: 327 myDpi = float(myDpi) 328 if optOut is not None: 329 n = optOut 330 for o in n.split(","): 331 savefig(o, dpi=myDpi) 332 if not options.blind: 333 show() 334 try: 335 fig.clf() 336 except: # noqa 337 pass 338 close() 339 gc.collect() 340 341 342def logNormalise(values, maxValue): 343 if not maxValue: 344 for e in values: 345 if not maxValue or maxValue < values[e]: 346 maxValue = values[e] 347 emin = None 348 emax = None 349 for e in values: 350 if values[e] != 0: 351 values[e] = log(values[e]) / log(maxValue) 352 if not emin or emin > values[e]: 353 emin = values[e] 354 if not emax or emax < values[e]: 355 emax = values[e] 356 if emax is not None and emin is not None: 357 valRange = emax - emin 358 if valRange == 0: 359 valRange = 1 360 for e in values: 361 values[e] = (values[e] - emin) / valRange 362 363 364def linNormalise(values, minColorValue, maxColorValue): 365 if minColorValue is not None and maxColorValue is not None: 366 valRange = maxColorValue - minColorValue 367 if valRange == 0: 368 valRange = 1 369 for e in values: 370 values[e] = (values[e] - minColorValue) / valRange 371 372 373def toHex(val): 374 """Converts the given value (0-255) into its hexadecimal representation""" 375 hex = "0123456789abcdef" 376 return hex[int(val / 16)] + hex[int(val - int(val / 16) * 16)] 377 378 379def toFloat(val): 380 """Converts the given value (0-255) into its hexadecimal representation""" 381 hex = "0123456789abcdef" 382 return float(hex.find(val[0]) * 16 + hex.find(val[1])) 383 384 385def toColor(val, colormap): 386 """Converts the given value (0-1) into a color definition parseable by matplotlib""" 387 for i in range(0, len(colormap) - 1): 388 if colormap[i + 1][0] > val: 389 scale = (val - colormap[i][0]) / \ 390 (colormap[i + 1][0] - colormap[i][0]) 391 r = colormap[i][1][0] + \ 392 (colormap[i + 1][1][0] - colormap[i][1][0]) * scale 393 g = colormap[i][1][1] + \ 394 (colormap[i + 1][1][1] - colormap[i][1][1]) * scale 395 b = colormap[i][1][2] + \ 396 (colormap[i + 1][1][2] - colormap[i][1][2]) * scale 397 return "#" + toHex(r) + toHex(g) + toHex(b) 398 return "#" + toHex(colormap[-1][1][0]) + toHex(colormap[-1][1][1]) + toHex(colormap[-1][1][2]) 399 400 401def parseColorMap(mapDef): 402 ret = {"red": [], "green": [], "blue": []} 403 defs = mapDef.split(",") 404 for d in defs: 405 (value, color) = d.split(":") 406 value = float(value) 407 r = color[1:3] 408 g = color[3:5] 409 b = color[5:7] 410 # ret.append( (float(value), ( toFloat(r), toFloat(g), toFloat(b) ) ) ) 411 ret["red"].append((value, toFloat(r) / 255., toFloat(r) / 255.)) 412 ret["green"].append((value, toFloat(g) / 255., toFloat(g) / 255.)) 413 ret["blue"].append((value, toFloat(b) / 255., toFloat(b) / 255.)) 414 415 # ret.append( (value, color) ) 416 colormap = matplotlib.colors.LinearSegmentedColormap("CUSTOM", ret, 1024) 417 return colormap 418 419 420def parseTicks(tickfile, mapping=None): 421 # there are multiple possible formats: 422 # 1. for defining the order (label is a data value or a wildcard): 423 # <LABEL> 424 # 2. for defining the tick positions for the data values 425 # <FLOAT>:<LABEL> 426 # 3. for defining the tick positions and a mapping from data values to displayed labels 427 # <FLOAT>:<DATA>:<LABEL> 428 429 # whether explicit tick positions are available 430 haveOffsets = True 431 # whether a data->label mapping is available 432 433 offsets = [] 434 labels = [] 435 with open(tickfile) as tf: 436 for line in tf: 437 line = line.strip() 438 if not line: 439 continue 440 of_label = line.split(':') 441 try: 442 of = float(of_label[0]) 443 offsets.append(of) 444 if len(of_label) > 1: 445 if len(of_label) == 3: 446 labels.append(of_label[2]) 447 if mapping is not None: 448 mapping[of_label[1]] = of_label[2] 449 else: 450 labels.append(' '.join(of_label[1:])) 451 else: 452 # also accept <FLOAT> format 453 labels.append(str(of)) 454 except ValueError: 455 haveOffsets = False 456 labels.append(line) 457 458 if not haveOffsets: 459 offsets = range(len(labels)) 460 return offsets, labels
mpl_version =
(3, 6, 3)
def
m2hm0(x, i):
def
m2hm1(x, i):
def
m2hm2(x, i):
def
addPlotOptions(ap):
73def addPlotOptions(ap): 74 ap.add_argument("--colors", dest="colors", category="visualization", 75 default=None, help="Defines the colors to use") 76 ap.add_argument("--colormap", dest="colormap", category="visualization", 77 default="nipy_spectral", help="Defines the colormap to use") 78 ap.add_argument("--colormap.center", dest="colormapCenter", type=float, category="visualization", 79 help="centers colors at the given value") 80 ap.add_argument("-l", "--labels", dest="labels", category="visualization", 81 default=None, help="Defines the labels to use") 82 ap.add_argument("--xlim", dest="xlim", category="visualization", 83 default=None, help="Defines x-limits of the figure XMIN,XMAX") 84 ap.add_argument("--ylim", dest="ylim", category="visualization", 85 default=None, help="Defines y-limits of the figure YMIN,YMAX") 86 ap.add_argument("--xticks", dest="xticks", category="visualization", 87 default=None, help="Set x-axis ticks XMIN,XMAX,XSTEP,XSIZE or XSIZE") 88 ap.add_argument("--yticks", dest="yticks", category="visualization", 89 default=None, help="Set y-axis ticks YMIN,YMAX,YSTEP,YSIZE or YSIZE") 90 ap.add_argument("--xticks-file", dest="xticksFile", category="input", type=ap.file, 91 default=None, help="Load x-axis ticks from file (LABEL or FLOAT:LABEL per line)") 92 ap.add_argument("--yticks-file", dest="yticksFile", category="input", type=ap.file, 93 default=None, help="Load y-axis ticks from file (LABEL or FLOAT:LABEL per line)") 94 ap.add_argument("--xtime0", dest="xtime0", action="store_true", category="time", 95 default=False, help="Use a time formatter for x-ticks (hh)") 96 ap.add_argument("--ytime0", dest="ytime0", action="store_true", category="time", 97 default=False, help="Use a time formatter for y-ticks (hh)") 98 ap.add_argument("--xtime1", dest="xtime1", action="store_true", category="time", 99 default=False, help="Use a time formatter for x-ticks (hh:mm)") 100 ap.add_argument("--ytime1", dest="ytime1", action="store_true", category="time", 101 default=False, help="Use a time formatter for y-ticks (hh:mm)") 102 ap.add_argument("--xtime2", dest="xtime2", action="store_true", category="time", 103 default=False, help="Use a time formatter for x-ticks (hh:mm:ss)") 104 ap.add_argument("--ytime2", dest="ytime2", action="store_true", category="time", 105 default=False, help="Use a time formatter for y-ticks (hh:mm:ss)") 106 ap.add_argument("--xgrid", dest="xgrid", action="store_true", category="visualization", 107 default=False, help="Enable grid on x-axis") 108 ap.add_argument("--ygrid", dest="ygrid", action="store_true", category="visualization", 109 default=False, help="Enable grid on y-axis") 110 ap.add_argument("--xticksorientation", dest="xticksorientation", category="visualization", 111 type=float, default=None, help="Set the orientation of the x-axis ticks") 112 ap.add_argument("--yticksorientation", dest="yticksorientation", category="visualization", 113 type=float, default=None, help="Set the orientation of the x-axis ticks") 114 ap.add_argument("--xlabel", dest="xlabel", category="visualization", 115 default=None, help="Set the x-axis label") 116 ap.add_argument("--ylabel", dest="ylabel", category="visualization", 117 default=None, help="Set the y-axis label") 118 ap.add_argument("--xlabelsize", dest="xlabelsize", category="visualization", 119 type=int, default=16, help="Set the size of the x-axis label") 120 ap.add_argument("--ylabelsize", dest="ylabelsize", category="visualization", 121 type=int, default=16, help="Set the size of the x-axis label") 122 ap.add_argument("--marker", dest="marker", default=None, category="visualization", 123 help="marker for single points (default o for scatter, None otherwise)") 124 ap.add_argument("--linestyle", dest="linestyle", default="-", category="visualization", 125 help="plot line style (default -)") 126 ap.add_argument("--title", dest="title", category="visualization", 127 default=None, help="Set the title") 128 ap.add_argument("--titlesize", dest="titlesize", category="visualization", 129 type=int, default=16, help="Set the title size") 130 ap.add_argument("--adjust", dest="adjust", category="visualization", 131 default=None, help="Adjust the subplots LEFT,BOTTOM or LEFT,BOTTOM,RIGHT,TOP") 132 ap.add_argument("-s", "--size", dest="size", category="visualization", 133 default=False, help="Defines the figure size X,Y") 134 ap.add_argument("--no-legend", dest="nolegend", action="store_true", category="visualization", 135 default=False, help="Disables the legend") 136 ap.add_argument("--legend-position", dest="legendposition", category="visualization", 137 default=None, help="Sets the legend position") 138 ap.add_argument("--dpi", dest="dpi", type=float, category="visualization", 139 default=None, help="Define dpi resolution for figures") 140 ap.add_argument("--alpha", type=float, 141 default=1., help="Define background transparency of the figure in the range 0..1")
def
addInteractionOptions(optParser):
144def addInteractionOptions(optParser): 145 optParser.add_option("-o", "--output", category="output", dest="output", metavar="FILE", 146 type=ArgumentParser.file_list, 147 default=None, help="Comma separated list of filename(s) the figure shall be written to") 148 optParser.add_option("-b", "--blind", dest="blind", action="store_true", 149 default=False, help="If set, the figure will not be shown")
def
addNetOptions(optParser):
def
applyPlotOptions(fig, ax, options):
159def applyPlotOptions(fig, ax, options): 160 if options.xlim: 161 xlim(float(options.xlim.split(",")[0]), float( 162 options.xlim.split(",")[1])) 163 if options.yticksorientation: 164 ax.tick_params( 165 axis='y', which='major', tickdir=options.xticksorientation) 166 if options.xticks: 167 vals = options.xticks.split(",") 168 if len(vals) == 1: 169 ax.tick_params(axis='x', which='major', labelsize=float(vals[0])) 170 elif len(vals) == 4: 171 xticks(arange(float(vals[0]), float(vals[1]), float(vals[2])), size=float(vals[3])) 172 else: 173 raise ValueError( 174 "Error: ticks must be given as one float (<SIZE>) or four floats (<MIN>,<MAX>,<STEP>,<SIZE>)") 175 if options.xticksFile: 176 xticks(*parseTicks(options.xticksFile)) 177 if options.xtime0: 178 if max(ax.get_xticks()) < 3600: 179 print("Warning: x ticks not suited for hh format.") 180 ax.xaxis.set_major_formatter(ff(m2hm0)) 181 if options.xtime1: 182 if max(ax.get_yticks()) < 60: 183 print("Warning: x ticks not suited for hh:mm format.") 184 ax.xaxis.set_major_formatter(ff(m2hm1)) 185 if options.xtime2: 186 ax.xaxis.set_major_formatter(ff(m2hm2)) 187 if options.xgrid: 188 ax.xaxis.grid(True) 189 if options.xlabel: 190 xlabel(options.xlabel, size=options.xlabelsize) 191 if options.xticksorientation: 192 labels = ax.get_xticklabels() 193 for label in labels: 194 label.set_rotation(options.xticksorientation) 195 196 if options.ylim: 197 ylim(float(options.ylim.split(",")[0]), float( 198 options.ylim.split(",")[1])) 199 if options.yticks: 200 vals = options.yticks.split(",") 201 if len(vals) == 1: 202 ax.tick_params(axis='y', which='major', labelsize=float(vals[0])) 203 elif len(vals) == 4: 204 yticks( 205 arange(float(vals[0]), float(vals[1]), float(vals[2])), size=float(vals[3])) 206 else: 207 raise ValueError( 208 "Error: ticks must be given as one float (<SIZE>) or four floats (<MIN>,<MAX>,<STEP>,<SIZE>)") 209 if options.yticksFile: 210 yticks(*parseTicks(options.yticksFile)) 211 if options.ytime0: 212 if max(ax.get_yticks()) < 3600: 213 print("Warning: y ticks not suited for hh format.") 214 ax.yaxis.set_major_formatter(ff(m2hm0)) 215 if options.ytime1: 216 if max(ax.get_yticks()) < 60: 217 print("Warning: y ticks not suited for hh:mm format.") 218 ax.yaxis.set_major_formatter(ff(m2hm1)) 219 if options.ytime2: 220 ax.yaxis.set_major_formatter(ff(m2hm2)) 221 if options.ygrid: 222 ax.yaxis.grid(True) 223 if options.ylabel: 224 ylabel(options.ylabel, size=options.ylabelsize) 225 if options.yticksorientation: 226 labels = ax.get_yticklabels() 227 for label in labels: 228 label.set_rotation(options.yticksorientation) 229 230 if options.title: 231 title(options.title, size=options.titlesize) 232 if options.adjust: 233 vals = options.adjust.split(",") 234 if len(vals) == 2: 235 fig.subplots_adjust(left=float(vals[0]), bottom=float(vals[1])) 236 elif len(vals) == 4: 237 fig.subplots_adjust(left=float(vals[0]), bottom=float( 238 vals[1]), right=float(vals[2]), top=float(vals[3])) 239 else: 240 raise ValueError( 241 "Error: adjust must be given as two floats (<LEFT>,<BOTTOM>) or four floats " + 242 "(<LEFT>,<BOTTOM>,<RIGHT>,<TOP>)") 243 if options.alpha is not None: 244 alpha = max(0., min(1., options.alpha)) 245 fig.patch.set_alpha(alpha) 246 ax.patch.set_alpha(alpha)
def
plotNet(net, colors, widths, options):
249def plotNet(net, colors, widths, options): 250 shapes = [] 251 c = [] 252 w = [] 253 for e in net._edges: 254 shapes.append(e.getShape()) 255 if e._id in colors: 256 c.append(colors[str(e._id)]) 257 else: 258 c.append(options.defaultColor) 259 if e._id in widths: 260 w.append(widths[str(e._id)]) 261 else: 262 w.append(options.defaultWidth) 263 264 line_segments = LineCollection(shapes, linewidths=w, colors=c, linestyles=options.linestyle) 265 ax = plt.gca() 266 ax.add_collection(line_segments) 267 ax.set_xmargin(0.1) 268 ax.set_ymargin(0.1) 269 ax.autoscale_view(True, True, True)
def
getColorMap(options):
def
getColor(options, i, a):
278def getColor(options, i, a): 279 if options.colors: 280 v = options.colors.split(",") 281 if i >= len(v): 282 raise ValueError("Error: not enough colors given") 283 return v[i] 284 if options.colormap[0] == '#': 285 colormap = parseColorMap(options.colormap[1:]) 286 if mpl_version < (3, 6, 0): 287 cm.register_cmap(name="CUSTOM", cmap=colormap) 288 else: 289 matplotlib.colormaps.register(name="CUSTOM", cmap=colormap) 290 options.colormap = "CUSTOM" 291 if options.colormapCenter: 292 cNorm = matplotlib.colors.TwoSlopeNorm(vmin=0, vcenter=options.colormapCenter, vmax=a) 293 else: 294 cNorm = matplotlib.colors.Normalize(vmin=0, vmax=a) 295 scalarMap = matplotlib.cm.ScalarMappable(norm=cNorm, cmap=getColorMap(options)) 296 return scalarMap.to_rgba(i)
def
getLabel(f, i, options):
def
openFigure(options):
def
closeFigure(fig, ax, options, haveLabels=True, optOut=None):
317def closeFigure(fig, ax, options, haveLabels=True, optOut=None): 318 if haveLabels and not options.nolegend: 319 if options.legendposition: 320 legend(loc=options.legendposition) 321 else: 322 legend() 323 applyPlotOptions(fig, ax, options) 324 if options.output or optOut is not None: 325 n = options.output 326 myDpi = options.dpi 327 if myDpi is not None: 328 myDpi = float(myDpi) 329 if optOut is not None: 330 n = optOut 331 for o in n.split(","): 332 savefig(o, dpi=myDpi) 333 if not options.blind: 334 show() 335 try: 336 fig.clf() 337 except: # noqa 338 pass 339 close() 340 gc.collect()
def
logNormalise(values, maxValue):
343def logNormalise(values, maxValue): 344 if not maxValue: 345 for e in values: 346 if not maxValue or maxValue < values[e]: 347 maxValue = values[e] 348 emin = None 349 emax = None 350 for e in values: 351 if values[e] != 0: 352 values[e] = log(values[e]) / log(maxValue) 353 if not emin or emin > values[e]: 354 emin = values[e] 355 if not emax or emax < values[e]: 356 emax = values[e] 357 if emax is not None and emin is not None: 358 valRange = emax - emin 359 if valRange == 0: 360 valRange = 1 361 for e in values: 362 values[e] = (values[e] - emin) / valRange
def
linNormalise(values, minColorValue, maxColorValue):
def
toHex(val):
374def toHex(val): 375 """Converts the given value (0-255) into its hexadecimal representation""" 376 hex = "0123456789abcdef" 377 return hex[int(val / 16)] + hex[int(val - int(val / 16) * 16)]
Converts the given value (0-255) into its hexadecimal representation
def
toFloat(val):
380def toFloat(val): 381 """Converts the given value (0-255) into its hexadecimal representation""" 382 hex = "0123456789abcdef" 383 return float(hex.find(val[0]) * 16 + hex.find(val[1]))
Converts the given value (0-255) into its hexadecimal representation
def
toColor(val, colormap):
386def toColor(val, colormap): 387 """Converts the given value (0-1) into a color definition parseable by matplotlib""" 388 for i in range(0, len(colormap) - 1): 389 if colormap[i + 1][0] > val: 390 scale = (val - colormap[i][0]) / \ 391 (colormap[i + 1][0] - colormap[i][0]) 392 r = colormap[i][1][0] + \ 393 (colormap[i + 1][1][0] - colormap[i][1][0]) * scale 394 g = colormap[i][1][1] + \ 395 (colormap[i + 1][1][1] - colormap[i][1][1]) * scale 396 b = colormap[i][1][2] + \ 397 (colormap[i + 1][1][2] - colormap[i][1][2]) * scale 398 return "#" + toHex(r) + toHex(g) + toHex(b) 399 return "#" + toHex(colormap[-1][1][0]) + toHex(colormap[-1][1][1]) + toHex(colormap[-1][1][2])
Converts the given value (0-1) into a color definition parseable by matplotlib
def
parseColorMap(mapDef):
402def parseColorMap(mapDef): 403 ret = {"red": [], "green": [], "blue": []} 404 defs = mapDef.split(",") 405 for d in defs: 406 (value, color) = d.split(":") 407 value = float(value) 408 r = color[1:3] 409 g = color[3:5] 410 b = color[5:7] 411 # ret.append( (float(value), ( toFloat(r), toFloat(g), toFloat(b) ) ) ) 412 ret["red"].append((value, toFloat(r) / 255., toFloat(r) / 255.)) 413 ret["green"].append((value, toFloat(g) / 255., toFloat(g) / 255.)) 414 ret["blue"].append((value, toFloat(b) / 255., toFloat(b) / 255.)) 415 416 # ret.append( (value, color) ) 417 colormap = matplotlib.colors.LinearSegmentedColormap("CUSTOM", ret, 1024) 418 return colormap
def
parseTicks(tickfile, mapping=None):
421def parseTicks(tickfile, mapping=None): 422 # there are multiple possible formats: 423 # 1. for defining the order (label is a data value or a wildcard): 424 # <LABEL> 425 # 2. for defining the tick positions for the data values 426 # <FLOAT>:<LABEL> 427 # 3. for defining the tick positions and a mapping from data values to displayed labels 428 # <FLOAT>:<DATA>:<LABEL> 429 430 # whether explicit tick positions are available 431 haveOffsets = True 432 # whether a data->label mapping is available 433 434 offsets = [] 435 labels = [] 436 with open(tickfile) as tf: 437 for line in tf: 438 line = line.strip() 439 if not line: 440 continue 441 of_label = line.split(':') 442 try: 443 of = float(of_label[0]) 444 offsets.append(of) 445 if len(of_label) > 1: 446 if len(of_label) == 3: 447 labels.append(of_label[2]) 448 if mapping is not None: 449 mapping[of_label[1]] = of_label[2] 450 else: 451 labels.append(' '.join(of_label[1:])) 452 else: 453 # also accept <FLOAT> format 454 labels.append(str(of)) 455 except ValueError: 456 haveOffsets = False 457 labels.append(line) 458 459 if not haveOffsets: 460 offsets = range(len(labels)) 461 return offsets, labels