Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/output/tripinfoByTAZ.py
169674 views
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
4
# Copyright (C) 2012-2025 German Aerospace Center (DLR) and others.
5
# This program and the accompanying materials are made available under the
6
# terms of the Eclipse Public License 2.0 which is available at
7
# https://www.eclipse.org/legal/epl-2.0/
8
# This Source Code may also be made available under the following Secondary
9
# Licenses when the conditions for such availability set forth in the Eclipse
10
# Public License 2.0 are satisfied: GNU General Public License, version 2
11
# or later which is available at
12
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
13
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
14
15
# @file tripinfoByTAZ.py
16
# @author Jakob Erdmann
17
# @date 2019-01-03
18
19
"""
20
Aggregate tripinfo statistics for TAZ-pairs. The relationship between tripinfos
21
and TAZ can be obtained from route files with 'fromTaz','toTaz' attributes or
22
from a TAZ-file.
23
"""
24
25
from __future__ import absolute_import
26
from __future__ import print_function
27
import os
28
import sys
29
from collections import defaultdict
30
sys.path.append(os.path.join(os.environ["SUMO_HOME"], 'tools'))
31
from sumolib.output import parse # noqa
32
from sumolib.options import ArgumentParser # noqa
33
from sumolib.miscutils import Statistics, parseTime # noqa
34
35
36
def get_options(args=None):
37
argParser = ArgumentParser()
38
argParser.add_argument("-t", "--tripinfo-file", dest="tripinfoFile",
39
help="tripinfo file written by the simulation")
40
argParser.add_argument("-r", "--route-files", dest="routeFiles",
41
help="demand input (trips, flows, vehicles) for reading fromTaz and toTaz info")
42
argParser.add_argument("-z", "--taz-files", dest="tazFiles",
43
help="taz definitions to assign trips to taz based on departure and arrival edge")
44
argParser.add_argument("-a", "--attribute", default="duration",
45
help="attribute to use for statistics")
46
argParser.add_argument("-o", "--output", help="the output file")
47
options = argParser.parse_args(args=args)
48
options.routeFiles = options.routeFiles.split(',') if options.routeFiles else []
49
options.tazFiles = options.tazFiles.split(',') if options.tazFiles else []
50
if not options.tripinfoFile:
51
sys.exit("Required argument --tripinfo-file is missing")
52
if not (options.routeFiles or options.tazFiles):
53
sys.exit("At least one --route-files or --taz-files must be defined")
54
return options
55
56
57
def writeTraveltimeMatrix(options):
58
id2TAZ = {} # vehicleID : (fromTaz, toTaz)
59
flowIds2TAZ = {} # flowID : (fromTaz, toTaz)
60
flowIDs = set()
61
sinkEdge2TAZ = {} # edgeID : TAZ
62
sourceEdge2TAZ = {} # edgeID : TAZ
63
attrs = defaultdict(lambda: ['id', 'fromTaz', 'toTaz'])
64
for routeFile in options.routeFiles:
65
for veh in parse(routeFile, ['trip', 'vehicle'], attrs):
66
if veh.fromTaz and veh.toTaz:
67
id2TAZ[veh.id] = (veh.fromTaz, veh.toTaz)
68
for flow in parse(routeFile, 'flow', attrs):
69
flowIDs.add(flow.id)
70
if flow.fromTaz and flow.toTaz:
71
flowIds2TAZ[flow.id] = (flow.fromTaz, flow.toTaz)
72
73
for tazFile in options.tazFiles:
74
for taz in parse(tazFile, 'taz'):
75
sourceEdges = []
76
sinkEdges = []
77
if taz.edges:
78
sourceEdges = taz.edges.split()
79
sinkEdges = sourceEdges
80
if taz.tazSource:
81
for ts in taz.tazSource:
82
sourceEdges.append(ts.id)
83
if taz.tazSink:
84
for ts in taz.tazSink:
85
sinkEdges.append(ts.id)
86
for e in sourceEdges:
87
if e in sourceEdge2TAZ:
88
print("edge %s s already assigned as source for taz %s. Reasignemnt to taz %s is not supported" % (
89
e, sourceEdge2TAZ[e], taz.id))
90
else:
91
sourceEdge2TAZ[e] = taz.id
92
for e in sinkEdges:
93
if e in sinkEdge2TAZ:
94
print("edge %s s already assigned as sink for taz %s. Reasignemnt to taz %s is not supported" % (
95
e, sinkEdge2TAZ[e], taz.id))
96
else:
97
sinkEdge2TAZ[e] = taz.id
98
99
odpairs = {}
100
for trip in parse(options.tripinfoFile, 'tripinfo'):
101
odpair = id2TAZ.get(trip.id)
102
tripID = trip.id
103
if odpair is None and '.' in trip.id:
104
flowID = trip.id[:trip.id.rfind('.')]
105
if flowID in flowIDs:
106
tripID = flowID
107
odpair = flowIds2TAZ.get(tripID)
108
if odpair is None:
109
fromEdge = trip.departLane[:trip.departLane.rfind('_')]
110
toEdge = trip.arrivalLane[:trip.arrivalLane.rfind('_')]
111
odpair = (sourceEdge2TAZ.get(fromEdge, '?'), sinkEdge2TAZ.get(toEdge, '?'))
112
if odpair not in odpairs:
113
odpairs[odpair] = Statistics(' '.join(odpair))
114
115
odpairs[odpair].add(parseTime(getattr(trip, options.attribute)), tripID)
116
117
if options.output:
118
with open(options.output, 'w') as outf:
119
outf.write('<tripinfosByTAZ attribute="%s">\n' % options.attribute)
120
for (fromTaz, toTaz), stats in sorted(odpairs.items()):
121
q1, median, q3 = stats.quartiles()
122
outf.write(' <odInfo fromTaz="%s" toTaz="%s" count="%s" min="%s" minVeh="%s"' %
123
(fromTaz, toTaz, stats.count(), stats.min, stats.min_label))
124
outf.write(' max="%s" maxVeh="%s" mean="%s" Q1="%s" median="%s" Q3="%s"/>\n' %
125
(stats.max, stats.max_label, stats.avg(), q1, median, q3))
126
outf.write('</tripinfosByTAZ>\n')
127
else:
128
for (fromTaz, toTaz), stats in sorted(odpairs.items()):
129
print(stats)
130
131
132
if __name__ == "__main__":
133
options = get_options()
134
writeTraveltimeMatrix(options)
135
136