Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/route/cutTrips.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 cutTrips.py
15
# @author Jakob Erdmann
16
# @date 2017-04-11
17
18
"""
19
Cut down trips from a large scenario to a sub-scenario.
20
Only trips that start and end in the sub-scenario network are kept
21
(This differs from cutRoutes.py which also keeps routes passing through the
22
sub-scenario network)
23
"""
24
from __future__ import absolute_import
25
from __future__ import print_function
26
27
import os
28
import sys
29
import codecs
30
31
from collections import defaultdict
32
import sort_routes
33
34
if 'SUMO_HOME' in os.environ:
35
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
36
sys.path.append(os.path.join(tools))
37
import sumolib # noqa
38
else:
39
sys.exit("please declare environment variable 'SUMO_HOME'")
40
41
42
def get_options(args=None):
43
USAGE = """Usage %(prog)s [options] <new_net.xml> <trips> [<trips2> ...]
44
If the given routes contain exit times these will be used to compute new
45
departure times. If the option --orig-net is given departure times will be
46
extrapolated based on edge-lengths and maximum speeds multiplied with --speed-factor"""
47
optParser = sumolib.options.ArgumentParser(usage=USAGE)
48
optParser.add_argument("-v", "--verbose", action="store_true",
49
default=False, help="Give more output")
50
optParser.add_argument("-o", "--trips-output", dest="output", category='output',
51
help="output trip file")
52
optParser.add_argument("-a", "--additional-input", category='input',
53
help="additional file for taz (must already be cut)")
54
optParser.add_argument("-b", "--big", action="store_true", default=False,
55
help="Perform out-of-memory sort using module sort_routes "
56
"(slower but more memory efficient)")
57
optParser.add_argument("network", category='input', help="Provide an input network")
58
optParser.add_argument("routeFiles", nargs="*", category='input',
59
help="If the given routes contain exit times, "
60
"these will be used to compute new departure times")
61
return optParser.parse_args(args=args)
62
63
64
def cut_trips(aEdges, options, validTaz):
65
areaEdges = set(aEdges)
66
num_trips = 0
67
num_returned = 0
68
69
for routeFile in options.routeFiles:
70
print("Parsing trips from %s" % routeFile)
71
for trip in sumolib.xml.parse(routeFile, 'trip'):
72
num_trips += 1
73
if trip.attr_from is not None and trip.attr_from not in areaEdges:
74
continue
75
if trip.to is not None and trip.to not in areaEdges:
76
continue
77
if trip.fromTaz is not None and trip.fromTaz not in validTaz:
78
continue
79
if trip.toTaz is not None and trip.toTaz not in validTaz:
80
continue
81
yield float(trip.depart), trip
82
num_returned += 1
83
84
print("Parsing persontrips from %s" % routeFile)
85
ignored_planitems = defaultdict(lambda: 0)
86
num_persons = 0
87
num_persontrips = 0
88
from_ok = 0
89
to_ok = 0
90
for person in sumolib.xml.parse(routeFile, 'person'):
91
num_persons += 1
92
if person.walk is not None:
93
ignored_planitems['walk'] += len(person.walk)
94
del person.walk
95
if person.stop is not None:
96
ignored_planitems['stop'] += len(person.stop)
97
del person.stop
98
if person.ride is not None:
99
ignored_planitems['ride'] += len(person.ride)
100
del person.ride
101
if person.personTrip is not None:
102
kept_pt = []
103
for pt in person.personTrip:
104
skip = False
105
if pt.attr_from in areaEdges:
106
from_ok += 1
107
else:
108
skip = True
109
if pt.to in areaEdges:
110
to_ok += 1
111
else:
112
skip = True
113
114
if skip:
115
continue
116
kept_pt.append(pt)
117
num_persontrips += 1
118
if kept_pt:
119
person.personTrip = kept_pt
120
yield float(person.depart), person
121
122
print("Parsed %s trips and kept %s" % (num_trips, num_returned))
123
if num_persons > 0:
124
print("Parsed %s persons and kept %s persontrips" % (num_trips,
125
num_persontrips))
126
print("Discared %s person that departed in the area and %s persons that arrived in the area" % (
127
from_ok, to_ok))
128
if ignored_planitems:
129
print("Ignored plan items:")
130
for itemtype, count in ignored_planitems.items():
131
print(" %s %ss" % (count, itemtype))
132
133
134
def writer(file, trip):
135
file.write(trip.toXML(' '))
136
137
138
def main(options):
139
net = sumolib.net.readNet(options.network)
140
edges = set([e.getID() for e in net.getEdges()])
141
print("Valid area contains %s edges" % len(edges))
142
143
def write_to_file(vehicles, f):
144
f.write('<!-- generated with %s for %s from %s -->\n' %
145
(os.path.basename(__file__), options.network, options.routeFiles))
146
f.write(
147
('<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
148
'xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/routes_file.xsd">\n'))
149
num_trips = 0
150
num_persons = 0
151
for _, v in vehicles:
152
if v.name == 'trip':
153
num_trips += 1
154
else:
155
num_persons += 1
156
writer(f, v)
157
f.write('</routes>\n')
158
if num_persons > 0:
159
print("Wrote %s trips and %s persons" % (num_trips, num_persons))
160
else:
161
print("Wrote %s trips" % (num_trips))
162
163
validTaz = set()
164
if options.additional_input:
165
for taz in sumolib.xml.parse(options.additional_input, 'taz'):
166
validTaz.add(taz.id)
167
168
if options.big:
169
# write output unsorted
170
tmpname = options.output + ".unsorted"
171
with codecs.open(tmpname, 'w', encoding='utf8') as f:
172
write_to_file(
173
cut_trips(edges, options, validTaz), f)
174
# sort out of memory
175
sort_routes.main([tmpname, '--big', '--outfile', options.output] + (['--verbose'] if options.verbose else []))
176
else:
177
routes = list(cut_trips(edges, options, validTaz))
178
routes.sort(key=lambda v: v[0])
179
with codecs.open(options.output, 'w', encoding='utf8') as f:
180
write_to_file(routes, f)
181
182
183
if __name__ == "__main__":
184
main(get_options())
185
186