Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/detector/routeUsage.py
169674 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2007-2025 German Aerospace Center (DLR) and others.
4
# This program and the accompanying materials are made available under the
5
# terms of the Eclipse Public License 2.0 which is available at
6
# https://www.eclipse.org/legal/epl-2.0/
7
# This Source Code may also be made available under the following Secondary
8
# Licenses when the conditions for such availability set forth in the Eclipse
9
# Public License 2.0 are satisfied: GNU General Public License, version 2
10
# or later which is available at
11
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
14
# @file routeUsage.py
15
# @author Jakob Erdmann
16
# @author Mirko Barthauer
17
# @date 2017-03-30
18
19
from __future__ import absolute_import
20
from __future__ import print_function
21
import os
22
import sys
23
from collections import defaultdict
24
25
if 'SUMO_HOME' in os.environ:
26
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
27
sys.path.append(os.path.join(tools))
28
import sumolib # noqa
29
from sumolib.output import parse # noqa
30
from sumolib.miscutils import Statistics # noqa
31
else:
32
sys.exit("please declare environment variable 'SUMO_HOME'")
33
34
35
def get_options():
36
USAGE = """Usage %(prog)s <emitters.xml> [<routes.xml>]"""
37
parser = sumolib.options.ArgumentParser(usage=USAGE)
38
parser.add_argument("-v", "--verbose", action="store_true",
39
default=False, help="Give more output")
40
parser.add_argument("--threshold", type=int, default=0,
41
help="Output routes that are used less than the threshold value")
42
parser.add_argument("--unused-output", category="output", type=parser.file,
43
help="Output route ids that are used less than the threshold value to file")
44
parser.add_argument("-r", "--flow-restrictions", dest="restrictionfile", category="output", type=parser.file,
45
help="Output route ids that are used more often than the threshold value given in file")
46
parser.add_argument("emitters", type=parser.file,
47
help="file path to emitter file", metavar="FILE")
48
parser.add_argument("routes", nargs="?", type=parser.file,
49
help="file path to route file", metavar="FILE")
50
options = parser.parse_args()
51
52
return options
53
54
55
def main():
56
options = get_options()
57
58
routes = defaultdict(list)
59
if options.routes is not None:
60
for route in parse(options.routes, 'route'):
61
routes[route.edges].append(route.id)
62
63
restrictions = {}
64
if options.restrictionfile is not None:
65
for line in open(options.restrictionfile):
66
count, edges = line.strip().split(None, 1)
67
for rID in routes[edges]:
68
restrictions[rID] = int(count)
69
70
routeUsage = defaultdict(int)
71
for flow in parse(options.emitters, 'flow'):
72
num = int(flow.number)
73
if flow.route is None:
74
dist = flow.routeDistribution[0]
75
probs = map(float, dist.probabilities.split())
76
probs = [p / sum(probs) for p in probs]
77
for rID, p in zip(dist.routes.split(), probs):
78
routeUsage[rID] += p * num
79
else:
80
routeUsage[flow.route] += num
81
82
usage = Statistics("routeUsage")
83
restrictUsage = Statistics("restrictedRouteUsage")
84
for rID, count in routeUsage.items():
85
usage.add(count, rID)
86
if rID in restrictions:
87
restrictUsage.add(count, rID)
88
print(usage)
89
print(restrictUsage, "total:", sum(restrictUsage.values))
90
91
if options.unused_output is not None:
92
with open(options.unused_output, 'w') as outf:
93
for rID, count in routeUsage.items():
94
if count <= options.threshold:
95
outf.write("%s\n" % rID)
96
if rID in restrictions and count > restrictions[rID]:
97
outf.write("%s %s %s\n" % (rID, count, restrictions[rID]))
98
99
100
if __name__ == "__main__":
101
main()
102
103