Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/detector/validate.py
169673 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2013-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 validate.py
15
# @author Michael Behrisch
16
# @date 2013-06-12
17
18
"""
19
This script validates detector data resulting from dfrouter
20
validation detectors against the original data fed into dfrouter
21
"""
22
from __future__ import print_function
23
from __future__ import absolute_import
24
import sys
25
import os
26
import collections
27
import matplotlib
28
matplotlib.use('Agg')
29
import matplotlib.pyplot as plt # noqa
30
sys.path.append(os.path.join(os.environ["SUMO_HOME"], 'tools'))
31
import sumolib # noqa
32
33
parser = sumolib.options.ArgumentParser(usage="usage: %(prog)s [options] <input_flows.csv>")
34
parser.add_argument(
35
"-d", "--detectorfile", type=parser.file, help="read detector list from file")
36
parser.add_argument(
37
"-v", "--validation", type=parser.file, help="read validation data from file")
38
parser.add_argument("-i", "--interval", default=15, type=parser.time,
39
help="aggregation interval in minutes (default: %(default)s)")
40
parser.add_argument("-l", "--legacy", action="store_true", default=False,
41
help="legacy style, input file is whitespace separated, detector_definition")
42
parser.add_argument("inputFlows", category="input", nargs=1, type=parser.file,
43
help="csv file with flow input", metavar="FILE")
44
options = parser.parse_args()
45
46
sources = set()
47
sinks = set()
48
dets = {}
49
sims = {}
50
detDef = "detector_definition" if options.legacy else "detectorDefinition"
51
if options.detectorfile:
52
for det in sumolib.output.parse_fast(options.detectorfile, detDef, ["id"]):
53
dets[det.id] = []
54
sims[det.id] = []
55
counts = {}
56
c = collections.defaultdict(int)
57
v = collections.defaultdict(float)
58
totals = collections.defaultdict(int)
59
countIn = 0
60
countOut = 0
61
start = 0
62
end = options.interval
63
with open(options.inputFlows) as f:
64
skipFirst = True
65
for line in f:
66
if skipFirst:
67
skipFirst = False
68
continue
69
if options.legacy:
70
item = line.split()
71
else:
72
item = line.split(";")
73
detId = item[0]
74
time = int(item[1])
75
if time >= end:
76
counts[start] = countIn - countOut
77
start = end
78
end += options.interval
79
for det, vals in dets.items():
80
if c[det] > 0:
81
vals.append((time, c[det], v[det] / c[det]))
82
c.clear()
83
v.clear()
84
if options.legacy:
85
total = int(item[3])
86
totalSpeed = float(item[2]) if total > 0 else 0.
87
else:
88
total = int(item[2]) + int(item[3])
89
totalSpeed = int(item[2]) * float(item[4]) + \
90
int(item[3]) * float(item[5])
91
c[detId] += total
92
v[detId] += totalSpeed
93
totals[detId] += total
94
if detId in sources:
95
countIn += total
96
if detId in sinks:
97
countOut += total
98
print("detIn: %s detOut: %s" % (countIn, countOut))
99
totalSim = collections.defaultdict(int)
100
if options.validation:
101
c.clear()
102
v.clear()
103
countIn = 0
104
countOut = 0
105
start = 0
106
end = options.interval
107
# <interval begin="0.00" end="60.00" id="validation_MQ11O_DS_FS1_ERU"
108
# nVehContrib="1" flow="60.00" occupancy="1.35" speed="6.19" length="5.00" nVehEntered="1"/>
109
for interval in sumolib.output.parse_fast(options.validation, "interval", ["begin", "id", "speed", "nVehEntered"]):
110
detId = interval.id[11:]
111
time = int(float(interval.begin) / 60)
112
if time >= end:
113
start = end
114
end += options.interval
115
for det, vals in sims.items():
116
if c[det] > 0:
117
vals.append((time, c[det], v[det] / c[det]))
118
c.clear()
119
v.clear()
120
c[detId] += int(interval.nVehEntered)
121
totalSim[detId] += int(interval.nVehEntered)
122
v[detId] += 3.6 * int(interval.nVehEntered) * float(interval.speed)
123
if detId in sources:
124
countIn += int(interval.nVehEntered)
125
if detId in sinks:
126
countOut += int(interval.nVehEntered)
127
print("simIn: %s simOut: %s" % (countIn, countOut))
128
129
for det, vals in dets.items():
130
print("Plotting", det, 'totaldet', totals[det], 'totalSim', totalSim[det])
131
plt.bar(*(zip(*vals)[:2])) # select first and second entry (time and flow)
132
if det in sims:
133
plt.plot(*(zip(*sims[det])[:2]))
134
plt.suptitle('%s flow, totalDet: %s, totalSim: %s' %
135
(det, totals[det], totalSim[det]))
136
plt.xlabel('time')
137
plt.ylabel('flow')
138
plt.ylim(0, 600)
139
plt.legend(["simulation", "measured value"])
140
plt.savefig('%s_flow.png' % det)
141
plt.close()
142
# select first and third entry (time and speed)
143
plt.bar(*(zip(*vals)[::2]))
144
if det in sims:
145
plt.plot(*(zip(*sims[det])[::2]))
146
plt.suptitle('%s_speed' % det)
147
plt.xlabel('time')
148
plt.ylabel('speed')
149
plt.ylim(0, 200)
150
plt.legend(["simulation", "measured value"])
151
plt.savefig('%s_speed.png' % det)
152
plt.close()
153
plt.bar(counts.keys(), counts.values())
154
plt.show()
155
156