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