def main(options): typeStats = dict() for trip in parse(options.tripinfoFile, 'tripinfo'): if trip.vType not in typeStats: typeStats[trip.vType] = Statistics(trip.vType) typeStats[trip.vType].add(parseTime(getattr(trip, options.attribute)), trip.id) for person in parse(options.tripinfoFile, 'personinfo'): for stage in person.getChildList(): if stage.hasAttribute(options.attribute): if stage.name not in typeStats: typeStats[stage.name] = Statistics(stage.name) typeStats[stage.name].add( parseTime(getattr(stage, options.attribute)), person.id) if options.output: with open(options.output, 'w') as outf: outf.write('<tripinfosByType attribute="%s">\n' % options.attribute) for vType, stats in sorted(typeStats.items()): q1, median, q3 = stats.quartiles() outf.write( ' <typeInfo vType="%s" count="%s" min="%s" minVeh="%s"' % (vType, stats.count(), stats.min, stats.min_label)) outf.write( ' max="%s" maxVeh="%s" mean="%s" Q1="%s" median="%s" Q3="%s"/>\n' % (stats.max, stats.max_label, stats.avg(), q1, median, q3)) outf.write('</tripinfosByType>\n') else: for vType, stats in sorted(typeStats.items()): print(stats)
def cut_stops(vehicle, busStopEdges, remaining, departShift=0, defaultDuration=0, isStandalone=False): if vehicle.stop: skippedStopDuration = 0 haveStop = False for stop in list(vehicle.stop): until = None if stop.until is None else parseTime(stop.until) if stop.busStop: if not busStopEdges: print("No bus stop locations parsed, skipping bus stop '%s'." % stop.busStop) elif stop.busStop not in busStopEdges: print("Skipping bus stop '%s', which could not be located." % stop.busStop) elif busStopEdges[stop.busStop] in remaining: if departShift > 0 and until is not None and isStandalone: stop.until = max(0, until - departShift) haveStop = True continue elif stop.duration is not None: skippedStopDuration += parseTime(stop.duration) else: skippedStopDuration += defaultDuration elif stop.lane[:-2] in remaining: haveStop = True continue if until is not None and not haveStop: if departShift < until: departShift = until vehicle.removeChild(stop) return departShift
def main(options): tf = humanReadableTime if options.hrTime else lambda x: x stopTimes = defaultdict(list) for routefile in options.routeFiles: for vehicle in sumolib.xml.parse(routefile, ['vehicle', 'trip'], heterogeneous=True): if vehicle.stop is None: continue for stop in vehicle.stop: if stop.parking in ["true", "True", "1" ] and options.ignoreParking: continue until = parseTime(stop.until) arrival = parseTime( stop.arrival) if stop.arrival else until - parseTime( stop.duration) stopTimes[stop.busStop].append((arrival, until, vehicle.id)) for stop, times in stopTimes.items(): times.sort() for i, (a, u, v) in enumerate(times): for a2, u2, v2 in times[i + 1:]: if u2 < u: print( "Vehicle %s (%s, %s) overtakes %s (%s, %s) at stop %s" % (v2, tf(a2), tf(u2), v, tf(a), tf(u), stop))
def markOvertaken(options, vehicleStopRoutes, stopRoutes): # mark stops that should not participate in constraint generation # once a vehice appears to be "overtaken" (based on inconsistent # arrival/until timing), all subsequent stops of that vehicle should no # longer be used for contraint generation for vehicle, stopRoute in vehicleStopRoutes.items(): overtaken = False for i, (edgesBefore, stop) in enumerate(stopRoute): if not (stop.hasAttribute("arrival") and stop.hasAttribute("until")): continue if options.skipParking and parseBool(stop.getAttributeSecure("parking", "false")): continue if not overtaken: arrival = parseTime(stop.arrival) until = parseTime(stop.until) for edgesBefore2, stop2 in stopRoutes[stop.busStop]: if stop2.vehID == stop.vehID: continue if not stop2.hasAttribute("arrival") or not stop2.hasAttribute("until"): continue if options.skipParking and parseBool(stop2.getAttributeSecure("parking", "false")): continue arrival2 = parseTime(stop2.arrival) until2 = parseTime(stop2.until) if arrival2 > arrival and until2 < until: overtaken = True print(("Vehicle %s (%s, %s) overtaken by %s (%s, %s) " + "at stop %s (index %s) and ignored afterwards") % (stop.vehID, humanReadableTime(arrival), humanReadableTime(until), stop2.vehID, humanReadableTime(arrival2), humanReadableTime(until2), stop.busStop, i), file=sys.stderr) break if overtaken: stop.setAttribute("invalid", True)
def main(options): # declare veh counts vehCounts = defaultdict(list) time = None for stop in sumolib.xml.parse(options.stopOutput, "stopinfo"): splace = stop.getAttributeSecure(options.stoppingPlace, "") if splace != "": vehCounts[splace].append((parseTime(stop.started), 1)) vehCounts[splace].append((parseTime(stop.ended), -1)) #iterate over vehCounts for splace, times in vehCounts.items(): times.sort() with open(splace + ".xml", "w") as outf: tPrev = None count = 0 # write header outf.write("<?xml version= \"1.0\" encoding=\"UTF-8\"?>\n\n") # open route rag outf.write("<stoppingPlace>\n") # iterate over trips for t, change in times: if t != tPrev and tPrev is not None: outf.write(" <step time=\"%s\" number=\"%s\"/>\n" % (tPrev, count)) count += change tPrev = t outf.write(" <step time=\"%s\" number=\"%s\"/>\n" % (t, count)) # close route tag outf.write("</stoppingPlace>\n")
def get_options(args=None): optParser = optparse.OptionParser() optParser.add_option("-o", "--output-file", dest="outfile", default="turnRatios.add.xml", help="define the output filename") optParser.add_option( "-r", "--route-files", dest="routefiles", help="define the route file seperated by comma(mandatory)") optParser.add_option( "-p", "--probabilities", dest="prob", action="store_true", default=False, help=" calculate the turning probabilities instead of traffic volumes") optParser.add_option("--id", default="generated", help="define the interval id") optParser.add_option("-b", "--begin", default="0", help="custom begin time (seconds or H:M:S)") optParser.add_option("-e", "--end", help="custom end time (seconds or H:M:S)") optParser.add_option("-i", "--interval", help="custom aggregation interval (seconds or H:M:S)") optParser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False, help="tell me what you are doing") (options, args) = optParser.parse_args(args=args) if not options.routefiles: optParser.print_help() sys.exit() if options.begin is not None: options.begin = parseTime(options.begin) if options.end is not None: options.end = parseTime(options.end) else: options.end = 1e20 if options.interval is not None: options.interval = parseTime(options.interval) options.routefiles = options.routefiles.split(',') return options
def main(options): tf = humanReadableTime if options.hrTime else lambda x: x stopTimes = defaultdict(list) for routefile in options.routeFiles: for vehicle in sumolib.xml.parse(routefile, ['vehicle', 'trip'], heterogeneous=True): if vehicle.stop is None: continue lastUntil = None for stop in vehicle.stop: if stop.parking in ["true", "True", "1"] and options.ignoreParking: continue if options.untilFromDuration: if stop.arrival: until = parseTime(stop.arrival) + parseTime(stop.duration) else: print("Cannot compute 'until' for Vehicle %s because 'arrival' is not defined" % vehicle.id, file=sys.stderr) else: until = parseTime(stop.until) arrival = parseTime(stop.arrival) if stop.arrival else until - parseTime(stop.duration) if until < arrival: print("Vehicle %s has 'until' before 'arrival' (%s, %s) at stop %s" % ( vehicle.id, tf(arrival), tf(until), stop.busStop), file=sys.stderr) # comparing lastUntil with arrival makes sense logically but # produces unnecessary warnings when using until times to encode small delays # # if lastUntil is not None and arrival < lastUntil: # print("Vehicle %s has 'arrival' (%s) before previous 'until' (%s) at stop %s" % ( # vehicle.id, tf(arrival), tf(lastUntil), stop.busStop), file=sys.stderr) if lastUntil is not None and until < lastUntil: print("Vehicle %s has 'until' (%s) before previous 'until' (%s) at stop %s" % ( vehicle.id, tf(until), tf(lastUntil), stop.busStop), file=sys.stderr) lastUntil = until stopTimes[stop.busStop].append((arrival, until, vehicle.id, stop.getAttributeSecure("tripId", ""))) for stop, times in stopTimes.items(): times.sort() for i, (a, u, v, t) in enumerate(times): for a2, u2, v2, t2 in times[i + 1:]: if u2 <= u: print("Vehicle %s (%s, %s) overtakes %s (%s, %s) at stop %s" % ( v2, tf(a2), tf(u2), v, tf(a), tf(u), stop), file=sys.stderr) if options.stopTable: if options.stopTable in stopTimes: times = stopTimes[options.stopTable] print("# busStop: %s" % options.stopTable) print("arrival\tuntil\tveh\ttripId") for a, u, v, t in sorted(times): print("%s\t%s\t%s\t%s" % (tf(a), tf(u), v, t)) else: print("No vehicle stops at busStop '%s' found" % options.stopTable, file=sys.stderr)
def startElement(self, name, attrs): if name in DEPART_ATTRS.keys(): startString = attrs[DEPART_ATTRS[name]] if startString == "triggered": self._depart = -1 else: self._depart = parseTime(startString) self._start_line = self.locator.getLineNumber() if name == "ride" and self._depart == -1 and "depart" in attrs: # this is at least the attempt to put triggered persons behind their vehicle # it probably works only for vehroute output self._depart = parseTime(attrs["depart"])
def parseTimeRange(fnames): begin = 1e20 end = 0 minInterval = 1e20 for fname in fnames: for interval in sumolib.xml.parse(fname, 'interval'): iBegin = parseTime(interval.begin) iEnd = parseTime(interval.end) begin = min(begin, iBegin) end = max(end, iEnd) minInterval = min(minInterval, iEnd - iBegin) return begin, end, minInterval
def main(options): tf = humanReadableTime if options.hrTime else lambda x: x stopTimes = defaultdict(list) for routefile in options.routeFiles: for vehicle in sumolib.xml.parse(routefile, ['vehicle', 'trip'], heterogeneous=True): if vehicle.stop is None: continue for stop in vehicle.stop: if stop.parking in ["true", "True", "1" ] and options.ignoreParking: continue if options.untilFromDuration: if stop.arrival: until = parseTime(stop.arrival) + parseTime( stop.duration) else: print( "Cannot compute 'until' for Vehicle %s because 'arrival' is not defined" % vehicle.id, file=sys.stderr) else: until = parseTime(stop.until) arrival = parseTime( stop.arrival) if stop.arrival else until - parseTime( stop.duration) stopTimes[stop.busStop].append( (arrival, until, vehicle.id, stop.getAttributeSecure("tripId", ""))) for stop, times in stopTimes.items(): times.sort() for i, (a, u, v, t) in enumerate(times): for a2, u2, v2, t2 in times[i + 1:]: if u2 <= u: print( "Vehicle %s (%s, %s) overtakes %s (%s, %s) at stop %s" % (v2, tf(a2), tf(u2), v, tf(a), tf(u), stop), file=sys.stderr) if options.stopTable: if options.stopTable in stopTimes: times = stopTimes[options.stopTable] print("# busStop: %s" % options.stopTable) print("arrival\tuntil\tveh\ttripId") for a, u, v, t in sorted(times): print("%s\t%s\t%s\t%s" % (tf(a), tf(u), v, t)) else: print("No vehicle stops at busStop '%s' found" % options.stopTable, file=sys.stderr)
def _cutEdgeList(areaEdges, oldDepart, exitTimes, edges, orig_net, options, stats, disconnected_action, startIdx=None, endIdx=None): startIdx = 0 if startIdx is None else int(startIdx) endIdx = len(edges) - 1 if endIdx is None else int(endIdx) firstIndex = getFirstIndex(areaEdges, edges[startIdx:endIdx + 1]) if firstIndex is None or firstIndex > endIdx: return [] # route does not touch the area lastIndex = endIdx - getFirstIndex(areaEdges, reversed(edges[:endIdx + 1])) if lastIndex < startIdx: return [] # route does not touch the area firstIndex += startIdx # check for connectivity route_parts = [(firstIndex + i, firstIndex + j) for i, j in missingEdges(areaEdges, edges[firstIndex:( lastIndex + 1)], stats.missingEdgeOccurences)] if len(route_parts) > 1: stats.multiAffectedRoutes += 1 if disconnected_action == 'discard': return None # loop over different route parts result = [] for fromIndex, toIndex in route_parts: if not hasMinLength(fromIndex, toIndex, edges, orig_net, options): stats.too_short += 1 continue # compute new departure if exitTimes is not None: departTimes = [oldDepart] + exitTimes.split()[:-1] teleportFactor = len(departTimes) / float(len(edges)) stats.teleportFactorSum += teleportFactor # assume teleports were spread evenly across the vehicles route newDepart = parseTime(departTimes[int(fromIndex * teleportFactor)]) if (exitTimes is None) or (newDepart == -1): if orig_net is not None: # extrapolate new departure using default speed newDepart = (parseTime(oldDepart) + sum( [(orig_net.getEdge(e).getLength() / (orig_net.getEdge(e).getSpeed() * options.speed_factor)) for e in edges[startIdx:fromIndex]])) else: newDepart = parseTime(oldDepart) result.append((newDepart, edges[fromIndex:toIndex + 1])) stats.num_returned += 1 return result
def parseDataIntervals(parseFun, fnames, begin, end, allRoutes, attr): locations = {} # edges -> CountData result = [] for fname in fnames: for interval in sumolib.xml.parse(fname, 'interval', heterogeneous=True): overlap = getOverlap(begin, end, parseTime(interval.begin), parseTime(interval.end)) if overlap > 0: # print(begin, end, interval.begin, interval.end, "overlap:", overlap) for edges, value in parseFun(interval, attr): if edges not in locations: result.append(CountData(0, edges, allRoutes)) locations[edges] = result[-1] locations[edges].addCount(int(value * overlap)) return result
def getIntervals(options): begin, end, interval = parseTimeRange(options.turnFiles + options.edgeDataFiles + options.odFiles) if options.begin is not None: begin = parseTime(options.begin) if options.end is not None: end = parseTime(options.end) if options.interval is not None: interval = parseTime(options.interval) result = [] while begin < end: result.append((begin, begin + interval)) begin += interval return result
def computeSignalTimes(options, net, stopRoutes): signalTimes = defaultdict(list) # signal -> [(timeAtSignal, stop), ...] debugInfo = [] for busStop, stops in stopRoutes.items(): for edgesBefore, stop in stops: if stop.hasAttribute("arrival"): arrival = parseTime(stop.arrival) elif stop.hasAttribute("until"): arrival = parseTime(stop.until) - parseTime( stop.getAttributeSecure("duration", "0")) else: continue for i, edge in enumerate(edgesBefore): node = net.getEdge(edge).getFromNode() if node.getType() == "rail_signal": tls = net.getTLS(node.getID()) for inLane, outLane, linkNo in tls.getConnections(): if outLane.getEdge().getID() == edge: signal = tls.getID() ttSignalStop = getTravelTime(net, edgesBefore[i:]) timeAtSignal = arrival - ttSignalStop signalTimes[signal].append((timeAtSignal, stop)) if signal == options.debugSignal: debugInfo.append(( timeAtSignal, "%s vehID=%s prevTripId=%s passes signal %s to stop %s arrival=%s ttSignalStop=%s edges=%s" % (humanReadableTime(timeAtSignal), stop.vehID, stop.prevTripId, signal, stop.busStop, humanReadableTime(arrival), ttSignalStop, edgesBefore))) break for signal in signalTimes.keys(): signalTimes[signal] = sorted(signalTimes[signal]) if options.debugSignal in signalTimes: debugInfo.sort() for t, info in debugInfo: print(info) busStops = set( [s.busStop for a, s in signalTimes[options.debugSignal]]) arrivals = [a for a, s in signalTimes[options.debugSignal]] print( "Signal %s is passed %s times between %s and %s on approach to stops %s" % (options.debugSignal, len(arrivals), arrivals[0], arrivals[-1], ' '.join(busStops))) return signalTimes
def sort_departs(routefilename, outfile): routes_doc = pulldom.parse(routefilename) vehicles = [] root = None for event, parsenode in routes_doc: if event == pulldom.START_ELEMENT: if root is None: root = parsenode.localName outfile.write("<%s>\n" % root) continue routes_doc.expandNode(parsenode) departAttr = DEPART_ATTRS.get(parsenode.localName) if departAttr is not None: startString = parsenode.getAttribute(departAttr) if startString == "triggered": start = -1 # before everything else else: start = parseTime(startString) vehicles.append( (start, parsenode.toprettyxml(indent="", newl=""))) else: # copy to output outfile.write(" " * 4 + parsenode.toprettyxml(indent="", newl="") + "\n") print('read %s elements.' % len(vehicles)) vehicles.sort(key=lambda v: v[0]) for depart, vehiclexml in vehicles: outfile.write(" " * 4) outfile.write(vehiclexml) outfile.write("\n") outfile.write("</%s>\n" % root) print('wrote %s elements.' % len(vehicles))
def getFlows(options): # get flows for each edge pair minDepart = 1e20 maxDepart = 0 begin = 0 interval = options.interval if options.interval is not None else 1e20 # intervalBegin -> edge -> followerEdge -> count intervalEdgePairFlowsMap = defaultdict(dict) for file in options.routefiles: if options.verbose: print("route file:%s" % file) for veh in sumolib.output.parse(file, 'vehicle'): depart = parseTime(veh.depart) if depart < options.begin or depart > options.end: continue edgesList = veh.route[0].edges.split() minDepart = min(minDepart, depart) maxDepart = max(maxDepart, depart) edgePairFlowsMap = intervalEdgePairFlowsMap[depart - depart % interval] for i, e in enumerate(edgesList): if i < len(edgesList) - 1: next = edgesList[i + 1] if e not in edgePairFlowsMap: edgePairFlowsMap[e] = {} if next not in edgePairFlowsMap[e]: edgePairFlowsMap[e][next] = 0 edgePairFlowsMap[e][next] += 1 if options.interval is None: yield intervalEdgePairFlowsMap[0], minDepart, maxDepart else: for begin, edgePairFlowsMap in intervalEdgePairFlowsMap.items(): yield edgePairFlowsMap, begin, begin + interval
def main(options): routes = defaultdict(list) # vehID -> recorded edges minSpeed = defaultdict(lambda: 1000) active = set() # vehicles that have passed the first filterRoute edge entryTime = {} # vehID -> time when entering corridor delayTime = { } # vehID -> time when vehicle speed first dropped below threshold for timestep, vehicle in parse_fast_nested(options.fcdfile, 'timestep', ['time'], 'vehicle', ['id', 'speed', 'lane']): time = parseTime(timestep.time) vehID = vehicle.id edge = vehicle.lane[0:vehicle.lane.rfind('_')] prevEdge = None if len(routes[vehID]) == 0 else routes[vehID][-1] if prevEdge != edge: if options.exit and prevEdge in options.exit: # vehicle has left the filtered corridor continue routes[vehID].append(edge) if vehID not in active: if not options.entry or edge in options.entry: # vehicle has entered the filtered corridor active.add(vehID) entryTime[vehID] = time else: continue speed = float(vehicle.speed) if speed < minSpeed[vehID]: minSpeed[vehID] = speed if speed < options.minspeed: delayTime[vehID] = time vehs = [] numDelayed = 0 for vehID, route in routes.items(): skip = False for required in options.filterRoute: if required not in route: skip = True break if not skip: if minSpeed[vehID] < options.minspeed: numDelayed += 1 vehs.append((entryTime[vehID], delayTime[vehID], vehID)) else: vehs.append((entryTime[vehID], -1, vehID)) vehs.sort() n = len(vehs) print("n=%s d=%s coordinationFactor=%.2f" % (n, numDelayed, (n - numDelayed) / float(n))) if options.fullOutput: with open(options.fullOutput, 'w') as outf: outf.write("# entryTime delayTime vehID\n") for record in vehs: outf.write(" ".join(map(str, record)) + "\n")
def getStopRoutes(options, stopEdges): """parse routes and determine the list of edges between stops return: setOfUniqueRoutes, busstopDict """ uniqueRoutes = set() stopRoutes = defaultdict(list) # busStop -> [(edges, stopObj), ....] vehicleStopRoutes = defaultdict(list) # vehID -> [(edges, stopObj), ....] numRoutes = 0 numStops = 0 begin = parseTime(options.begin) for vehicle in sumolib.xml.parse(options.routeFile, 'vehicle', heterogeneous=True): depart = parseTime(vehicle.depart) if depart < begin: continue numRoutes += 1 edges = tuple(vehicle.route[0].edges.split()) uniqueRoutes.add(edges) lastIndex = -1 routeIndex = 0 tripId = vehicle.id line = vehicle.getAttributeSecure("line", "") for stop in vehicle.stop: numStops += 1 if stop.busStop is None: stop.setAttribute("busStop", stop.lane) stopEdges[stop.lane] = sumolib._laneID2edgeID(stop.lane) stopEdge = stopEdges[stop.busStop] while edges[routeIndex] != stopEdge: routeIndex += 1 assert (routeIndex < len(edges)) edgesBefore = edges[lastIndex + 1:routeIndex + 1] stop.setAttribute("prevTripId", tripId) stop.setAttribute("prevLine", line) stop.setAttribute("vehID", vehicle.id) tripId = stop.getAttributeSecure("tripId", tripId) line = stop.getAttributeSecure("line", line) stopRoutes[stop.busStop].append((edgesBefore, stop)) vehicleStopRoutes[vehicle.id].append((edgesBefore, stop)) lastIndex = routeIndex print("read %s routes (%s unique) and %s stops at %s busStops" % (numRoutes, len(uniqueRoutes), numStops, len(stopRoutes))) return uniqueRoutes, stopRoutes, vehicleStopRoutes
def get_options(args=None): parser = sumolib.options.ArgumentParser( description="Compute Stopping Place usage") parser.add_argument("-s", "--stop-output-file", dest="stopOutput", help="simulation stop-output file") parser.add_argument("-t", "--stopping-place", dest="stoppingPlace", help="stoppingPlace type (busStop, parkingArea...)", default="busStop") parser.add_argument("--csv", action="store_true", default=False, help="write in CSV format") parser.add_argument("--containers", action="store_true", default=False, help="count containers instead of persons") parser.add_argument( "--only-changes", action="store_true", default=False, dest="onlyChanges", help="write output only for steps where the occupancy changes") parser.add_argument("-b", "--begin", default=None, help="begin time (when writting all steps)") parser.add_argument("-e", "--end", default=None, help="end time (when writting all steps)") options = parser.parse_args(args=args) if not options.stopOutput: parser.print_help() sys.exit() if options.begin: options.begin = int(parseTime(options.begin)) if options.end: options.end = int(parseTime(options.end)) return options
def parseDataIntervals(parseFun, fnames, begin, end, allRoutes, attr, options, isOD=False, warn=False): locations = {} # edges -> CountData result = [] for fname in fnames: for interval in sumolib.xml.parse(fname, 'interval', heterogeneous=True): overlap = getOverlap(begin, end, parseTime(interval.begin), parseTime(interval.end)) if overlap > 0: # print(begin, end, interval.begin, interval.end, "overlap:", overlap) for edges, value in parseFun(interval, attr): try: value = float(value) except TypeError: if warn: print( "Warning: Missing '%s' value in file '%s' for edge(s) '%s'" % (attr, fname, ' '.join(edges)), file=sys.stderr) continue if edges not in locations: result.append( CountData(0, edges, allRoutes, isOD, options)) locations[edges] = result[-1] elif isOD != locations[edges].isOD: print( "Warning: Edge relation '%s' occurs as turn relation and also as OD-relation" % ' '.join(edges), file=sys.stderr) locations[edges].addCount(int(value * overlap)) return result
def main(options): intervals = defaultdict(dict) # time -> (type -> stats) for trip in parse(options.tripinfoFile, 'tripinfo'): typeStats = intervals[getAggregatedTime(options, trip)] if trip.vType not in typeStats: typeStats[trip.vType] = Statistics(trip.vType) typeStats[trip.vType].add(parseTime(getattr(trip, options.attribute)), trip.id) for person in parse(options.tripinfoFile, 'personinfo'): for stage in person.getChildList(): if stage.hasAttribute(options.attribute): typeStats = intervals[getAggregatedTime(options, stage)] if stage.name not in typeStats: typeStats[stage.name] = Statistics(stage.name) typeStats[stage.name].add(parseTime(getattr(stage, options.attribute)), person.id) if options.output: with open(options.output, 'w') as outf: sumolib.writeXMLHeader(outf, "$Id$", "tripinfosByType", options=options) # noqa for time in sorted(intervals.keys()): typeStats = intervals[time] if time is not None: outf.write(' <interval begin="%s" end="%s">\n' % (time, time + options.interval)) for vType, stats in sorted(typeStats.items()): q1, median, q3 = stats.quartiles() outf.write(' <typeInfo vType="%s" count="%s" min="%s" minVeh="%s"' % (vType, stats.count(), stats.min, stats.min_label)) outf.write(' max="%s" maxVeh="%s" mean="%s" Q1="%s" median="%s" Q3="%s"/>\n' % (stats.max, stats.max_label, stats.avg(), q1, median, q3)) if time is not None: outf.write(' </interval>\n') outf.write('</tripinfosByType>\n') else: for time in sorted(intervals.keys()): typeStats = intervals[time] if time is not None: print("Interval: [%s, %s[" % (time, time + options.interval)) for vType, stats in sorted(typeStats.items()): print(stats)
def get_options(args=None): argParser = ArgumentParser() argParser.add_argument("-t", "--tripinfo-file", dest="tripinfoFile", help="tripinfo file written by the simulation") argParser.add_argument("-a", "--attribute", default="duration", help="attribute to use for statistics") argParser.add_argument("-o", "--output", help="the output file") argParser.add_argument("-i", "--interval", help="custom aggregation interval (seconds or H:M:S)") argParser.add_argument("--by-arrivals", action="store_true", default=False, dest="byArrivals", help="When using --interval, aggregated by arrival time instead of depart time") options = argParser.parse_args(args=args) if not options.tripinfoFile: sys.exit("Required argument --tripinfo-file is missing") if options.interval is not None: options.interval = parseTime(options.interval) return options
def parseTimed(outf, options): departCounts = defaultdict(lambda: 0) arrivalCounts = defaultdict(lambda: 0) intermediateCounts = defaultdict(lambda: 0) lastDepart = 0 period = options.period if options.period else options.end begin = options.begin periodEnd = options.period if options.period else options.end for elem in parse(options.routefile, options.elements2): depart = elem.depart if elem.depart is not None else elem.begin if depart != "triggered": depart = parseTime(depart) lastDepart = depart if depart < lastDepart: sys.stderr.write("Unsorted departure %s for %s '%s'" % (depart, elem.tag, elem.id)) lastDepart = depart if depart < begin: continue if depart >= periodEnd or depart >= options.end: description = "%s-%s " % (begin, periodEnd) writeInterval(outf, options, departCounts, arrivalCounts, intermediateCounts, begin, periodEnd, description) periodEnd += period begin += period if depart >= options.end: break number = getFlowNumber(elem) if elem.name == 'flow' else 1 src, dst, edges = getEdges(elem, options.taz) filterBy = [src, dst] if options.taz or not edges else edges if not hasSubpart(filterBy, options.subparts): continue departCounts[src] += number arrivalCounts[dst] += number if options.intermediate: for e in edges: intermediateCounts[e] += number description = "%s-%s " % (begin, periodEnd) if periodEnd != END_UNLIMITED else "" if len(departCounts) > 0: writeInterval(outf, options, departCounts, arrivalCounts, intermediateCounts, begin, lastDepart, description)
def parseTimed(outf, options): departCounts = defaultdict(lambda: 0) arrivalCounts = defaultdict(lambda: 0) intermediateCounts = defaultdict(lambda: 0) lastDepart = 0 period = options.period if options.period else options.end begin = options.begin periodEnd = options.period if options.period else options.end for elem in parse(options.routefile, options.elements2): depart = elem.depart if depart != "triggered": depart = parseTime(depart) lastDepart = depart if depart < lastDepart: sys.stderr.write("Unsorted departure %s for %s '%s'" % (depart, elem.tag, elem.id)) lastDepart = depart if depart < begin: continue if depart >= periodEnd or depart >= options.end: description = "%s-%s " % (begin, periodEnd) writeInterval(outf, options, departCounts, arrivalCounts, intermediateCounts, begin, periodEnd, description) periodEnd += period begin += period if depart >= options.end: break if elem.route: edges = elem.route[0].edges.split() if not hasSubpart(edges, options.subparts): continue departCounts[edges[0]] += 1 arrivalCounts[edges[-1]] += 1 for e in edges: intermediateCounts[e] += 1 description = "%s-%s " % (begin, periodEnd) if len(departCounts) > 0: writeInterval(outf, options, departCounts, arrivalCounts, intermediateCounts, begin, lastDepart, description)
def main(options): if options.seed: random.seed(options.seed) with open(options.out, 'w') as outf: pat = re.compile(r'(.* duration=")([^"]*)(".*)') for line in open(options.routeFile): if "<stop" in line and "duration" in line: if random.random() < options.probability: if options.min == options.max: delay = options.min else: delay = None while (delay is None or delay < options.min or delay > options.max): delay = random.gauss(options.mean, options.dev) mo = pat.match(line) newDuration = int((parseTime(mo.group(2)) + delay)) line = mo.group(1) + str(newDuration) + mo.group(3) + "\n" outf.write(line)
def get_options(args=None): optParser = sumolib.options.ArgumentParser( description="Add fromTaz and toTaz to a route file") optParser.add_argument("-r", "--route-file", dest="routefile", help="define the input route file (mandatory)") optParser.add_argument( "-a", "-taz-files", dest="tazfiles", help="define the files to load TAZ (districts) from (mandatory)") optParser.add_argument("-o", "--output-file", dest="outfile", help="define the output filename (mandatory)") optParser.add_argument("-i", "--interval", help="define the output aggregation interval") optParser.add_argument("--id", default="DEFAULT_VEHTYPE", dest="intervalID", help="define the output aggregation interval") optParser.add_argument("-s", "--seed", type=int, default=42, help="random seed") options = optParser.parse_args(args=args) if not options.routefile or not options.tazfiles or not options.outfile: optParser.print_help() sys.exit(1) if options.interval is not None: options.interval = parseTime(options.interval) options.tazfiles = options.tazfiles.split() return options
def get_options(args=None): parser = sumolib.options.ArgumentParser( description="Sample routes to match counts") parser.add_argument("-n", "--net-file", dest="netFile", help="Input network file") parser.add_argument("-a", "--additional-file", dest="addFile", help="Input additional file (busStops)") parser.add_argument( "-t", "--trip-file", dest="tripFile", help="Input trip file (will be processed into a route file)") parser.add_argument( "-r", "--route-file", dest="routeFile", help="Input route file (must contain routed vehicles rather than trips)" ) parser.add_argument("-o", "--output-file", dest="out", default="constraints.add.xml", help="Output additional file") parser.add_argument( "-b", "--begin", default="0", help= "ignore vehicles departing before the given begin time (seconds or H:M:S)" ) parser.add_argument( "--until-from-duration", action="store_true", default=False, dest="untilFromDuration", help= "Use stop arrival+duration instead of 'until' to compute insertion constraints" ) parser.add_argument( "-d", "--delay", default="0", help= "Assume given maximum delay when computing the number of intermediate vehicles " + "that pass a given signal (for setting limit)") parser.add_argument( "-l", "--limit", type=int, default=0, help= "Increases the limit value for tracking passed vehicles by the given amount" ) parser.add_argument( "--abort-unordered", dest="abortUnordered", action="store_true", default=False, help="Abort generation of constraints for a stop " "once the ordering of vehicles by 'arrival' differs from the ordering by 'until'" ) parser.add_argument( "-p", "--ignore-parking", dest="ignoreParking", action="store_true", default=False, help= "Ignore unordered timing if the vehicle which arrives first is parking" ) parser.add_argument( "-P", "--skip-parking", dest="skipParking", action="store_true", default=False, help= "Do not generate constraints for a vehicle that parks at the next stop" ) parser.add_argument("--comment.line", action="store_true", dest="commentLine", default=False, help="add lines of involved trains in comment") parser.add_argument( "--comment.id", action="store_true", dest="commentId", default=False, help= "add ids of involved trains in comment (when different from tripId)") parser.add_argument("-v", "--verbose", action="store_true", default=False, help="tell me what you are doing") parser.add_argument( "--debug-switch", dest="debugSwitch", help="print debug information for the given merge-switch edge") parser.add_argument("--debug-signal", dest="debugSignal", help="print debug information for the given signal id") parser.add_argument( "--debug-stop", dest="debugStop", help="print debug information for the given busStop id") options = parser.parse_args(args=args) if (options.routeFile is None and options.tripFile is None) or options.netFile is None: parser.print_help() sys.exit() if options.routeFile is None: options.routeFile = options.tripFile + ".rou.xml" args = [ DUAROUTER, '-n', options.netFile, '-r', options.tripFile, '-a', options.addFile, '-o', options.routeFile, '--ignore-errors', '--no-step-log', ] print("calling", " ".join(args)) sys.stdout.flush() subprocess.call(args) sys.stdout.flush() options.delay = parseTime(options.delay) return options
def findInsertionConflicts(options, net, stopEdges, stopRoutes, vehicleStopRoutes): """find routes that start at a stop with a traffic light at end of the edge and routes that pass this stop. Ensure insertion happens in the correct order""" # signal -> [(tripID, otherSignal, otherTripID, limit, line, otherLine, vehID, otherVehID), ...] conflicts = defaultdict(list) numConflicts = 0 numIgnoredConflicts = 0 for busStop, stops in stopRoutes.items(): stopEdge = stopEdges[busStop] node = net.getEdge(stopEdge).getToNode() signal = node.getID() untils = [] for edgesBefore, stop in stops: if stop.hasAttribute("until") and not options.untilFromDuration: until = parseTime(stop.until) elif stop.hasAttribute("arrival"): until = parseTime(stop.arrival) + parseTime( stop.getAttributeSecure("duration", "0")) else: continue untils.append((until, edgesBefore, stop)) # only use 'until' for sorting and keep the result stable otherwise untils.sort(key=itemgetter(0)) prevPassing = None ignore = False for i, (nUntil, nEdges, nStop) in enumerate(untils): nVehStops = vehicleStopRoutes[nStop.vehID] nIndex = nVehStops.index((nEdges, nStop)) nIsPassing = nIndex < len(nVehStops) - 1 nIsDepart = len(nEdges) == 1 if options.verbose and busStop == options.debugStop: print(i, "n:", humanReadableTime(nUntil), nStop.tripId, nStop.vehID, nIndex, len(nVehStops), "passing:", nIsPassing, "depart:", nIsDepart) if prevPassing is not None and nIsDepart: pUntil, pEdges, pStop = prevPassing pVehStops = vehicleStopRoutes[pStop.vehID] pIndex = pVehStops.index((pEdges, pStop)) # no need to constrain subsequent departures (simulation should maintain ordering) if len(pEdges) > 1 or pIndex > 0: # find edges after stop if busStop == options.debugStop: print(i, "p:", humanReadableTime(pUntil), pStop.tripId, pStop.vehID, pIndex, len(pVehStops), "n:", humanReadableTime(nUntil), nStop.tripId, nStop.vehID, nIndex, len(nVehStops)) if nIsPassing: # both vehicles move past the stop pNextEdges = pVehStops[pIndex + 1][0] nNextEdges = nVehStops[nIndex + 1][0] limit = 1 # recheck pSignal = signal nSignal = signal if node.getType() != "rail_signal": # find signal in nextEdges pSignal = findSignal(net, pNextEdges) nSignal = findSignal(net, nNextEdges) if pSignal is None or nSignal is None: print(( "Ignoring insertion conflict between %s and %s at stop '%s' " + "because no rail signal was found after the stop" ) % (nStop.prevTripId, pStop.prevTripId, busStop), file=sys.stderr) continue # check for inconsistent ordering if (ignore or (options.abortUnordered and pStop.hasAttribute("arrival") and nStop.hasAttribute("arrival") and (not options.ignoreParking or not parseBool( nStop.getAttributeSecure("parking", "false"))) and parseTime(pStop.arrival) > parseTime( nStop.arrival))): numIgnoredConflicts += 1 # ignore conflict and any that follow if not ignore: # sort output by arrival again print( "Found inconsistent times at stop %s " "for vehicle %s (%s, %s) and vehicle %s (%s, %s)" % (busStop, nStop.vehID, humanReadableTime( parseTime(nStop.arrival)), humanReadableTime(nUntil), pStop.vehID, humanReadableTime( parseTime(pStop.arrival)), humanReadableTime(pUntil)), file=sys.stderr) ignore = True continue # predecessor tripId after stop is needed pTripId = pStop.getAttributeSecure( "tripId", pStop.vehID) conflicts[nSignal].append(( nStop.prevTripId, pSignal, pTripId, limit, # attributes for adding comments nStop.prevLine, pStop.prevLine, nStop.vehID, pStop.vehID)) numConflicts += 1 if busStop == options.debugStop: print( " found insertionConflict pSignal=%s nSignal=%s pTripId=%s" % (pSignal, nSignal, pTripId)), if nIsPassing: prevPassing = (nUntil, nEdges, nStop) print("Found %s insertion conflicts" % numConflicts) if numIgnoredConflicts > 0: print("Ignored %s insertion conflicts" % (numIgnoredConflicts)) return conflicts
def findConflicts(options, switchRoutes, mergeSignals, signalTimes): """find stops that target the same busStop from different branches of the prior merge switch and establish their ordering""" numConflicts = 0 numIgnoredConflicts = 0 # signal -> [(tripID, otherSignal, otherTripID, limit, line, otherLine, vehID, otherVehID), ...] conflicts = defaultdict(list) ignoredVehicles = set() for switch, stopRoutes2 in switchRoutes.items(): numSwitchConflicts = 0 numIgnoredSwitchConflicts = 0 if switch == options.debugSwitch: print("Switch %s lies ahead of busStops %s" % (switch, stopRoutes2.keys())) for busStop, stops in stopRoutes2.items(): arrivals = [] for edges, stop in stops: if stop.hasAttribute("arrival"): arrival = parseTime(stop.arrival) elif stop.hasAttribute("until"): arrival = parseTime(stop.until) - parseTime( stop.getAttributeSecure("duration", "0")) else: print( "ignoring stop at %s without schedule information (arrival, until)" % busStop) continue arrivals.append((arrival, edges, stop)) arrivals.sort(key=itemgetter(0)) ignore = False for (pArrival, pEdges, pStop), (nArrival, nEdges, nStop) in zip(arrivals[:-1], arrivals[1:]): pSignal, pTimeSiSt = mergeSignals[(switch, pEdges)] nSignal, nTimeSiSt = mergeSignals[(switch, nEdges)] if switch == options.debugSwitch: print(pSignal, nSignal, pStop, nStop) if pSignal != nSignal and pSignal is not None and nSignal is not None: if (ignore or (options.abortUnordered and pStop.hasAttribute("until") and nStop.hasAttribute("until") and (not options.ignoreParking or not parseBool( pStop.getAttributeSecure("parking", "false"))) and parseTime(pStop.until) > parseTime(nStop.until))): numIgnoredConflicts += 1 numIgnoredSwitchConflicts += 1 # ignore conflict and any that follow if not ignore: print( "Found inconsistent times at stop %s " "for vehicle %s (%s, %s) and vehicle %s (%s, %s)" % (busStop, pStop.vehID, humanReadableTime(pArrival), humanReadableTime(parseTime(pStop.until)), nStop.vehID, humanReadableTime(nArrival), humanReadableTime(parseTime(nStop.until))), file=sys.stderr) # ignoredVehicles.insert(pStop.vehID) ignoredVehicles.add(nStop.vehID) ignore = True continue if (options.abortUnordered and nStop.vehID in ignoredVehicles): # no constraints for inconsistent vehicle to avoid deadlock numIgnoredConflicts += 1 numIgnoredSwitchConflicts += 1 continue if options.skipParking and parseBool( nStop.getAttributeSecure("parking", "false")): print( "ignoring stop at %s for parking vehicle %s (%s, %s)" % (busStop, nStop.vehID, humanReadableTime(nArrival), (humanReadableTime(parseTime(nStop.until)) if nStop.hasAttribute("until") else "-"))) numIgnoredConflicts += 1 numIgnoredSwitchConflicts += 1 continue if options.skipParking and parseBool( pStop.getAttributeSecure("parking", "false")): print( "ignoring stop at %s for %s (%s, %s) after parking vehicle %s (%s, %s)" % (busStop, nStop.vehID, humanReadableTime(nArrival), (humanReadableTime(parseTime(nStop.until)) if nStop.hasAttribute("until") else "-"), pStop.vehID, humanReadableTime(pArrival), (humanReadableTime(parseTime(pStop.until)) if pStop.hasAttribute("until") else "-"))) numIgnoredConflicts += 1 numIgnoredSwitchConflicts += 1 continue numConflicts += 1 numSwitchConflicts += 1 # check for trains that pass the switch in between the # current two trains (heading to another stop) and raise the limit limit = 1 pTimeAtSignal = pArrival - pTimeSiSt nTimeAtSignal = nArrival - nTimeSiSt end = nTimeAtSignal + options.delay if options.verbose and options.debugSignal == pSignal: print( "check vehicles between %s and %s (including delay %s) at signal %s pStop=%s nStop=%s" % (humanReadableTime(pTimeAtSignal), humanReadableTime(end), options.delay, pSignal, pStop, nStop)) limit += countPassingTrainsToOtherStops( options, pSignal, busStop, pTimeAtSignal, end, signalTimes) conflicts[nSignal].append(( nStop.prevTripId, pSignal, pStop.prevTripId, limit, # attributes for adding comments nStop.prevLine, pStop.prevLine, nStop.vehID, pStop.vehID)) if options.verbose: print("Found %s conflicts at switch %s" % (numSwitchConflicts, switch)) if numIgnoredSwitchConflicts > 0: print("Ignored %s conflicts at switch %s" % (numIgnoredSwitchConflicts, switch)) print("Found %s conflicts" % numConflicts) if numIgnoredConflicts > 0: print("Ignored %s conflicts" % numIgnoredConflicts) return conflicts
def writeTraveltimeMatrix(options): id2TAZ = {} # vehicleID : (fromTaz, toTaz) flowIds2TAZ = {} # flowID : (fromTaz, toTaz) flowIDs = set() sinkEdge2TAZ = {} # edgeID : TAZ sourceEdge2TAZ = {} # edgeID : TAZ attrs = defaultdict(lambda: ['id', 'fromTaz', 'toTaz']) for routeFile in options.routeFiles: for veh in parse(routeFile, ['trip', 'vehicle'], attrs): if veh.fromTaz and veh.toTaz: id2TAZ[veh.id] = (veh.fromTaz, veh.toTaz) for flow in parse(routeFile, 'flow', attrs): flowIDs.add(flow.id) if flow.fromTaz and flow.toTaz: flowIds2TAZ[flow.id] = (flow.fromTaz, flow.toTaz) for tazFile in options.tazFiles: for taz in parse(tazFile, 'taz'): sourceEdges = [] sinkEdges = [] if taz.edges: sourceEdges = taz.edges.split() sinkEdges = sourceEdges if taz.tazSource: for ts in taz.tazSource: sourceEdges.append(ts.id) if taz.tazSink: for ts in taz.tazSink: sinkEdges.append(ts.id) for e in sourceEdges: if e in sourceEdge2TAZ: print( "edge %s s already assigned as source for taz %s. Reasignemnt to taz %s is not supported" % (e, sourceEdge2TAZ[e], taz.id)) else: sourceEdge2TAZ[e] = taz.id for e in sinkEdges: if e in sinkEdge2TAZ: print( "edge %s s already assigned as sink for taz %s. Reasignemnt to taz %s is not supported" % (e, sinkEdge2TAZ[e], taz.id)) else: sinkEdge2TAZ[e] = taz.id odpairs = {} for trip in parse(options.tripinfoFile, 'tripinfo'): odpair = id2TAZ.get(trip.id) tripID = trip.id if odpair is None and '.' in trip.id: flowID = trip.id[:trip.id.rfind('.')] if flowID in flowIDs: tripID = flowID odpair = flowIds2TAZ.get(tripID) if odpair is None: fromEdge = trip.departLane[:trip.departLane.rfind('_')] toEdge = trip.arrivalLane[:trip.arrivalLane.rfind('_')] odpair = (sourceEdge2TAZ.get(fromEdge, '?'), sinkEdge2TAZ.get(toEdge, '?')) if odpair not in odpairs: odpairs[odpair] = Statistics(' '.join(odpair)) odpairs[odpair].add(parseTime(getattr(trip, options.attribute)), tripID) if options.output: with open(options.output, 'w') as outf: outf.write('<tripinfosByTAZ attribute="%s">\n' % options.attribute) for (fromTaz, toTaz), stats in sorted(odpairs.items()): q1, median, q3 = stats.quartiles() outf.write( ' <odInfo fromTaz="%s" toTaz="%s" count="%s" min="%s" minVeh="%s"' % (fromTaz, toTaz, stats.count(), stats.min, stats.min_label)) outf.write( ' max="%s" maxVeh="%s" mean="%s" Q1="%s" median="%s" Q3="%s"/>\n' % (stats.max, stats.max_label, stats.avg(), q1, median, q3)) outf.write('</tripinfosByTAZ>\n') else: for (fromTaz, toTaz), stats in sorted(odpairs.items()): print(stats)
def writeTraveltimeMatrix(options): id2TAZ = {} # vehicleID : (fromTaz, toTaz) flowIds2TAZ = {} # flowID : (fromTaz, toTaz) flowIDs = set() sinkEdge2TAZ = {} # edgeID : TAZ sourceEdge2TAZ = {} # edgeID : TAZ attrs = defaultdict(lambda: ['id', 'fromTaz', 'toTaz']) for routeFile in options.routeFiles: for veh in parse(routeFile, ['trip', 'vehicle'], attrs): if veh.fromTaz and veh.toTaz: id2TAZ[veh.id] = (veh.fromTaz, veh.toTaz) for flow in parse(routeFile, 'flow', attrs): flowIDs.add(flow.id) if flow.fromTaz and flow.toTaz: flowIds2TAZ[flow.id] = (flow.fromTaz, flow.toTaz) for tazFile in options.tazFiles: for taz in parse(tazFile, 'taz'): sourceEdges = [] sinkEdges = [] if taz.edges: sourceEdges = taz.edges.split() sinkEdges = sourceEdges if taz.tazSource: for ts in taz.tazSource: sourceEdges.append(ts.id) if taz.tazSink: for ts in taz.tazSink: sinkEdges.append(ts.id) for e in sourceEdges: if e in sourceEdge2TAZ: print("edge %s s already assigned as source for taz %s. Reasignemnt to taz %s is not supported" % ( e, sourceEdge2TAZ[e], taz.id)) else: sourceEdge2TAZ[e] = taz.id for e in sinkEdges: if e in sinkEdge2TAZ: print("edge %s s already assigned as sink for taz %s. Reasignemnt to taz %s is not supported" % ( e, sinkEdge2TAZ[e], taz.id)) else: sinkEdge2TAZ[e] = taz.id odpairs = {} for trip in parse(options.tripinfoFile, 'tripinfo'): odpair = id2TAZ.get(trip.id) tripID = trip.id if odpair is None and '.' in trip.id: flowID = trip.id[:trip.id.rfind('.')] if flowID in flowIDs: tripID = flowID odpair = flowIds2TAZ.get(tripID) if odpair is None: fromEdge = trip.departLane[:trip.departLane.rfind('_')] toEdge = trip.arrivalLane[:trip.arrivalLane.rfind('_')] odpair = (sourceEdge2TAZ.get(fromEdge, '?'), sinkEdge2TAZ.get(toEdge, '?')) if odpair not in odpairs: odpairs[odpair] = Statistics(' '.join(odpair)) odpairs[odpair].add(parseTime(getattr(trip, options.attribute)), tripID) if options.output: with open(options.output, 'w') as outf: outf.write('<tripinfosByTAZ attribute="%s">\n' % options.attribute) for (fromTaz, toTaz), stats in sorted(odpairs.items()): q1, median, q3 = stats.quartiles() outf.write(' <odInfo fromTaz="%s" toTaz="%s" count="%s" min="%s" minVeh="%s"' % (fromTaz, toTaz, stats.count(), stats.min, stats.min_label)) outf.write(' max="%s" maxVeh="%s" mean="%s" Q1="%s" median="%s" Q3="%s"/>\n' % (stats.max, stats.max_label, stats.avg(), q1, median, q3)) outf.write('</tripinfosByTAZ>\n') else: for (fromTaz, toTaz), stats in sorted(odpairs.items()): print(stats)