Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/detector/edgeDataFromFlow.py
169673 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 edgeDataFromFlow.py
15
# @author Jakob Erdmann
16
# @author Mirko Barthauer
17
# @date 2020-02-27
18
19
"""
20
This script converts a flow file in csv-format to XML
21
(generalized meandata format : http://sumo.dlr.de/xsd/meandata_file.xsd)
22
"""
23
from __future__ import absolute_import
24
from __future__ import print_function
25
import sys
26
import os
27
28
from collections import defaultdict
29
30
import detector
31
32
SUMO_HOME = os.environ.get('SUMO_HOME',
33
os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..'))
34
sys.path.append(os.path.join(SUMO_HOME, 'tools'))
35
import sumolib # noqa
36
from sumolib.xml import parse # noqa
37
from sumolib.options import ArgumentParser # noqa
38
DEBUG = False
39
40
41
def get_options(args=None):
42
parser = ArgumentParser(description="Convert detector flow file to edgeData format")
43
parser.add_argument("-d", "--detector-file", dest="detfile", category="input", type=ArgumentParser.additional_file,
44
help="read detectors from FILE", metavar="FILE")
45
parser.add_argument("-f", "--detector-flow-file", dest="flowfile", category="input", type=ArgumentParser.file,
46
help="read detector flows to compare to from FILE (mandatory)", metavar="FILE")
47
parser.add_argument("-o", "--output-file", dest="output", category="output", type=ArgumentParser.edgedata_file,
48
help="output edgeData FILE (mandatory)", metavar="FILE")
49
parser.add_argument("--id-column", default="Detector", dest="detcol",
50
help="Read detector ids from the given column")
51
parser.add_argument("--time-column", default="Time", dest="timecol",
52
help="Read detector time from the given column")
53
parser.add_argument("--time-scale", type=int, default=60, dest="timescale",
54
help="Interpretation of time units in seconds (default 60)")
55
parser.add_argument("-q", "--flow-columns", dest="flowcols", default="qPKW,qLKW", type=str,
56
help="which columns contains flows (specified via column header)", metavar="STRING")
57
parser.add_argument("-b", "--begin", default=0, type=ArgumentParser.time,
58
help="custom begin time (minutes or H:M:S)")
59
parser.add_argument("-e", "--end", default=1440, type=ArgumentParser.time,
60
help="custom end time (minutes or H:M:S)")
61
parser.add_argument("-i", "--interval", default=1440, type=ArgumentParser.time,
62
help="custom aggregation interval (minutes or H:M:S)")
63
parser.add_argument("--cadyts", action="store_true",
64
default=False, help="generate output in cadyts format")
65
parser.add_argument("-v", "--verbose", action="store_true", dest="verbose",
66
default=False, help="tell me what you are doing")
67
options = parser.parse_args(args=args)
68
if not options.flowfile or not options.output:
69
parser.print_help()
70
sys.exit()
71
72
return options
73
74
75
class LaneMap:
76
def get(self, key, default):
77
return key[0:-2]
78
79
80
def main(options):
81
readers = {}
82
flowcols = options.flowcols.split(',')
83
tMin = None
84
tMax = None
85
for flowcol in flowcols:
86
detReader = detector.DetectorReader(options.detfile, LaneMap())
87
tMin, tMax = detReader.findTimes(options.flowfile, tMin, tMax, options.detcol, options.timecol)
88
hasData = detReader.readFlows(options.flowfile, flow=flowcol, det=options.detcol,
89
time=options.timecol, timeVal=0, timeMax=1440)
90
if options.verbose:
91
print("flowColumn: %s hasData: %s" % (flowcol, hasData))
92
readers[flowcol] = detReader
93
94
if options.verbose:
95
print("found data from minute %s to %s" % (int(tMin), int(tMax)))
96
97
ts = options.timescale
98
beginM = int(sumolib.miscutils.parseTime(options.begin, ts) / ts)
99
intervalM = int(sumolib.miscutils.parseTime(options.interval, ts) / ts)
100
endM = min(int(sumolib.miscutils.parseTime(options.end, ts) / ts), tMax)
101
102
with open(options.output, "w") as outf:
103
root = "measurements" if options.cadyts else "data"
104
sumolib.xml.writeHeader(outf)
105
outf.write('<%s>\n' % root)
106
while beginM <= endM:
107
iEndM = beginM + intervalM
108
edges = defaultdict(dict) # edge : {attr:val}
109
maxGroups = defaultdict(lambda: 0) # edge : nGroups
110
111
for flowcol in flowcols:
112
detReader = detector.DetectorReader(options.detfile, LaneMap())
113
detReader.readFlows(options.flowfile, flow=flowcol, det=options.detcol, time=options.timecol,
114
timeVal=beginM, timeMax=iEndM, addDetectors=(options.detfile is None))
115
for edge, detData in detReader._edge2DetData.items():
116
maxFlow = 0
117
nGroups = 0
118
for group in detData:
119
if group.isValid:
120
maxFlow = max(maxFlow, group.totalFlow)
121
nGroups += 1
122
# if options.verbose:
123
# print("flowColumn: %s edge: %s flow: %s groups: %s" % (
124
# flowcol, edge, maxFlow, nGroups))
125
edges[edge][flowcol] = maxFlow
126
maxGroups[edge] = max(maxGroups[edge], nGroups)
127
128
if options.cadyts:
129
for edge in sorted(edges.keys()):
130
print(' <singlelink link="%s" start="%s" end="%s" value="%s" stddev="8" type="COUNT_VEH"/>' %
131
(edge, beginM * ts, iEndM * ts, sum(edges[edge].values())), file=outf)
132
else:
133
outf.write(' <interval id="flowdata" begin="%s" end="%s">\n' % (beginM * ts, iEndM * ts))
134
for edge in sorted(edges.keys()):
135
attrs = ' '.join(['%s="%s"' % (k, v) for k, v in sorted(edges[edge].items())])
136
outf.write(' <edge id="%s" %s groups="%s"/>\n' % (edge, attrs, nGroups))
137
outf.write(' </interval>\n')
138
beginM += intervalM
139
outf.write('</%s>\n' % root)
140
141
142
if __name__ == "__main__":
143
main(get_options())
144
145