Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/route/analyzePersonPlans.py
169674 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2012-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 analyzePersonPlans.py
15
# @author Jakob Erdmann
16
# @date 2019-09-13
17
18
"""
19
Count the number of different person plans in a route file
20
"""
21
from __future__ import absolute_import
22
from __future__ import print_function
23
24
import os
25
import sys
26
from collections import defaultdict
27
28
if 'SUMO_HOME' in os.environ:
29
sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))
30
import sumolib # noqa
31
32
33
def get_options(args=None):
34
parser = sumolib.options.ArgumentParser(description="Analyze person plans")
35
parser.add_argument("-r", "--route-files", category='input', dest="routeFiles", help="Input route files")
36
parser.add_argument("-w", "--merge-walks", dest="mergeWalks", action="store_true", help="merge subsequent walks")
37
parser.add_argument("-p", "--public-prefixes", dest="public", help="Distinguish public transport modes by prefix")
38
parser.add_argument("-i", "--ids", dest="ids", default=0, type=int,
39
help="List the given number of person ids for each type of plan")
40
options = parser.parse_args(args=args)
41
if options.routeFiles is None:
42
parser.print_help()
43
sys.exit()
44
if options.public:
45
options.public = options.public.split(',')
46
else:
47
options.public = []
48
return options
49
50
51
def stageName(options, person, stage):
52
if stage.name == 'ride':
53
# see MSStageTrip::getVehicles for customary prefix of automatically spawned vehicles
54
if stage.lines is None:
55
return 'public'
56
elif stage.lines.startswith(person.id + "_"):
57
return 'car'
58
elif stage.lines == 'taxi':
59
return 'taxi'
60
else:
61
if stage.intended is not None:
62
for pType in options.public:
63
if pType in stage.intended:
64
return pType
65
return 'public'
66
else:
67
return stage.name
68
69
70
def main(options):
71
counts = defaultdict(lambda: list())
72
for routeFile in options.routeFiles.split(','):
73
for person in sumolib.xml.parse(routeFile, 'person'):
74
stages = tuple([stageName(options, person, s) for s in person.getChildList()])
75
if options.mergeWalks:
76
filtered = []
77
for s in stages:
78
if len(filtered) == 0 or s != filtered[-1]:
79
filtered.append(s)
80
stages = tuple(filtered)
81
counts[stages].append(person.id)
82
83
numPersons = sum(map(len, counts.values()))
84
print("Loaded %s persons" % numPersons)
85
maxPadding = max(map(len, [' '.join(k) for k, v in counts.items()]))
86
countSize = len(str(max([len(p) for k, p in counts.items()])))
87
formatStr = "%" + str(countSize) + "s: %s%s"
88
reverseCounts = [(len(p), k) for k, p in counts.items()]
89
for count, k in sorted(reverseCounts):
90
stages = ' '.join(k)
91
examples = ""
92
if options.ids > 0:
93
padding = " " * (maxPadding - len(stages))
94
examples = padding + " - " + ','.join(counts[k][:options.ids])
95
print(formatStr % (count, stages, examples))
96
97
98
if __name__ == "__main__":
99
main(get_options())
100
101