1#!/usr/local/bin/python3.8 2# -*- coding: utf-8 -*- 3# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo 4# Copyright (C) 2012-2019 German Aerospace Center (DLR) and others. 5# This program and the accompanying materials 6# are made available under the terms of the Eclipse Public License v2.0 7# which accompanies this distribution, and is available at 8# http://www.eclipse.org/legal/epl-v20.html 9# SPDX-License-Identifier: EPL-2.0 10 11# @file analyze_teleports.py 12# @author Jakob Erdmann 13# @author Michael Behrisch 14# @date 2012-11-20 15# @version $Id$ 16 17from __future__ import absolute_import 18from __future__ import print_function 19import sys 20import re 21from collections import defaultdict 22 23 24def parse_log(logfile, edges=True, aggregate=3600): 25 print("Parsing %s" % logfile) 26 reFrom = re.compile("lane='([^']*)'") 27 reFromMeso = re.compile("edge '([^']*)'") 28 reTime = re.compile("time.(\d*)\.") 29 reHRTime = re.compile("time.(\d):(\d\d):(\d\d):(\d*).") 30 # counts per lane 31 waitingCounts = defaultdict(lambda: 0) 32 collisionCounts = defaultdict(lambda: 0) 33 # counts per step 34 waitingStepCounts = defaultdict(lambda: 0) 35 collisionStepCounts = defaultdict(lambda: 0) 36 for index, line in enumerate(open(logfile)): 37 try: 38 if "Warning: Teleporting vehicle" in line: 39 # figure out whether its micro or meso 40 match = reFrom.search(line) 41 if match is None: 42 edge = reFromMeso.search(line).group(1) 43 else: 44 edge = match.group(1) 45 if edges: 46 edge = edge[:-2] 47 timeMatch = reTime.search(line) 48 if timeMatch: 49 time = int(timeMatch.group(1)) 50 else: 51 timeMatch = reHRTime.search(line) 52 time = (24 * 3600 * int(timeMatch.group(1)) 53 + 3600 * int(timeMatch.group(2)) 54 + 60 * int(timeMatch.group(3)) 55 + int(timeMatch.group(4))) 56 if "collision" in line: 57 collisionCounts[edge] += 1 58 collisionStepCounts[time / aggregate] += 1 59 else: 60 waitingCounts[edge] += 1 61 waitingStepCounts[time / aggregate] += 1 62 except Exception: 63 print(sys.exc_info()) 64 sys.exit("error when parsing line '%s'" % line) 65 if index % 1000 == 0: 66 sys.stdout.write(".") 67 sys.stdout.flush() 68 print() 69 print("read %s lines" % index) 70 71 return (waitingCounts, collisionCounts, 72 waitingStepCounts, collisionStepCounts) 73 74 75def print_counts(countDict, label, num=10): 76 counts = sorted(countDict.items(), key=lambda k: -k[1]) 77 print(label, "worst %s edges: " % num, counts[:num]) 78 print(label, 'total:', sum(countDict.values())) 79 80 81def main(logfile): 82 waitingCounts, collisionCounts, waitingStepCounts, collisionStepCounts = parse_log(logfile) 83 print_counts(waitingCounts, 'waiting') 84 print_counts(collisionCounts, 'collisions') 85 # generate plot 86 if len(waitingStepCounts) + len(collisionStepCounts) > 0: 87 min_step = min(waitingStepCounts.keys() + collisionStepCounts.keys()) 88 max_step = max(waitingStepCounts.keys() + collisionStepCounts.keys()) 89 plotfile = logfile + '.plot' 90 with open(plotfile, 'w') as f: 91 f.write(("# plot '%s' using 1:2 with lines title 'waiting', '%s' using 1:3 with lines title " + 92 "'collisions'\n") % (plotfile, plotfile)) 93 for step in range(min_step, max_step + 1): 94 print(' '.join( 95 map(str, [step, waitingStepCounts[step], collisionStepCounts[step]])), file=f) 96 with open(logfile + "data.xml", 'w') as f: 97 print('<meandata>\n <interval begin="0" end="100:00:00:00">', file=f) 98 for item in waitingCounts.items(): 99 print(' <edge id="%s" waiting_teleport="%s"/>' % item, file=f) 100 print(" </interval>\n</meandata>", file=f) 101 102 103if __name__ == "__main__": 104 main(*sys.argv[1:]) 105