Skripte mit Zeitreihen erstellen

Technische Mitteilung #57
März 2021

Von Tessa Hayman

Tessa Hayman führt Sie durch die Komplexität der Verarbeitung von Zeitreihen über Python-Skripte und erklärt, wie Sie Ihre eigenen Zeitreihen so erstellen, dass sie in der Bedienoberfläche visualisiert werden können.

Was sind Zeitreihen?

Eine Zeitreihe ist ein Satz von Daten, die sich auf ein Objekt beziehen und sich im zeitlichen Verlauf ändern. So wird zum Beispiel die Zählung auf einer Strecke mit den Werten für jedes Erfassungsintervall, beispielsweise 15 Minuten, in einer Zeitreihe gespeichert.

In Aimsun Next können Sie Zeitreihen in der Zeitreihen-Registerkarte eines Objekts ansehen. Beispiel für einen Simulationslauf:

Eine Zeitreihe ist ein Objekt der Klasse GKTimeSerie und wird in einem Attribut der Art GKColumndes entsprechenden Objekts gespeichert. Aus dem Objekt GKTimeSeriekann die Standardabweichung sowie Max, Min, Mean und der Effektivwert RMS ausgelesen werden..

Jeder GKTimeSerie -Zeitreihe ist ein entsprechendes Beschreibungsobjekt (GKTSDescription) zugeordnet.). Dieses enthält Informationen über die Dauer, die Start- und Endzeit sowie das jeweilige Zeitreihenintervall.

Um auf ein bestimmtes Zeitreihenintervall zuzugreifen, für das Sie einen Wert lesen oder schreiben möchten, wird das ObjektGKTimeSerieIndex verwendet. Um das 5. Zeitreihenintervall anzugeben, verwenden Sie also GKTimeSerieIndex(4) , da die Nummerierung bei 0 beginnt.

Daten aus einer Zeitreihe auslesen

Um eine Zeitreihe aus einem Objekt auszulesen, rufen Sie die Methode getDataValueTS() auf und übergeben als Argument die GKColumn- Spalte, in der diese gespeichert ist.

Wenn Sie den Wert eines Zeitintervalls direkt aus der Zeitreihe eines Objekts abrufen möchten, können Sie stattdessen die Methode»getDataValueInTS()«aufrufen und dabei neben der»GKColumn«, in der die Zeitreihe gespeichert ist, auch den Index»GKTimeSerieIndex«als Argument übergeben.

Beachten Sie, dass»getDataValueInTS()«ein Tupel zurückgibt, bei dem das erste Element der Zeitreihenwert und das zweite die Abweichung darstellt.

Um einen bestimmten Spaltennamen zu finden, können Sie entweder nach Abruf einer Datenbank oder Ausführen des Modells im »Types«-Fenster nachsehen. Unten sind als Beispiel die Ausgaben für „GKSection“ abgebildet.

Der Name setzt sich aus folgenden Angaben zusammen:

  • STATISCH oder DYNAMISCH
  • Objekttyp
  • Bezeichnung der Ausgabe
  • ID des Simulationslaufs
  • ID des Fahrzeugtyps (bzw. „0“ für alle Fahrzeuge)
  • Fahrstreifennummer (bzw. „0“ für alle Fahrspuren)

Um die Verkehrsdichte auf einem Fahrstreifen einer bestimmten Strecke während eines bestimmten Simulationszeitintervalls auszulesen, können Sie z. B. die folgende Funktion verwenden. Beachten Sie, dass das erste Zeitintervall mit „0“ und das zweite mit „1“ usw. beschriftet ist.

				
					def readdensity( section, interval, replicationid, lanenumber, vehicleid=0 ):
column = model.getColumn( "DYNAMIC::GKSection_density_"+str(replicationid)+"_"+str(vehicleid)+"_"+str(lanenumber) )
	(value, deviation) = section.getDataValueInTS( column, GKTimeSerieIndex(interval) )
	return value

				
			

Daten in eine Zeitreihe schreiben

Um neue Zeitreihen zu erstellen, gehen Sie folgendermaßen vor:

  • Erstellen Sie die Spalte, in welcher die den einzelnen Objekten eines bestimmten Typs zugeordnete Zeitreihe gespeichert werden soll.
  • Erstellen Sie eine Zeitreihenbeschreibung (GKTSDescription), die mindestens die Startzeit, die Endzeit, das Zeitreihenintervall sowie optional den Nullwert und die Berechnungsweise eines aggregierten Wertes für den gesamten Zeitraum definiert.
  • Rufen Sie beim Ausführen der Objektschleife erst die Intervallschleife und dann die Methode setDataValueInTS() auf, um das jeweilige Intervall mit dem entsprechenden Wert zu füllen.

Das folgende Skript erzeugt z. B. eine Zeitreihe für Knoten, in der die Umlaufzeit des in diesem Tageszeitraum aktiven Signalprogramms gespeichert wird. Es überprüft den vom Signalprogrammplan abgedeckten Zeitraum in Intervallen von jeweils 15 Minuten. Weisen Sie das Skript dem Kontextmenü der Signalprogrammpläne zu, und führen Sie dieses mit einem Rechtsklick auf einen beliebigen Signalprogrammplan aus.

				
					fromDate = QDateTime(QDate().currentDate(), target.initialTime())
toDate = fromDate.addSecs(target.duration().toSeconds()[0])
interval = GKTimeDuration(0, 15, 0)
fromDate = fromDate.addSecs(interval.toSeconds()[0])

type = model.getType("GKNode")
column = type.getColumn( "GKNode::cycle_%s" % target.getId(), GKType.eSearchOnlyThisType )
if column == None:
	column = type.addColumn( "GKNode::cycle_%s" % target.getId(), GK.BuildContents("Cycle Time", target), GKColumn._GKTimeSerie, GKColumn.eExternal )
column.setConversion(GK.eConversionUndefined, "", "")

tsDescription = GKTSDescription.getCreateDescription( column, "cycleTime" )
tsDescription.setAggregationType(GK.eAggregationUndefined)
tsDescription.setNullValue(-1)
tsDescription.setTime(fromDate, toDate, interval)

now = fromDate
while now <= toDate:
	fromTime = now.time().second()+now.time().minute()*60+now.time().hour()*3600
	for node in model.getCatalog().getObjectsByType(type).itervalues():
		controlJunction = target.getControlJunction(node.getId(), fromTime, fromTime+1)[0]
		if controlJunction != None:
			cycle = controlJunction.getCycle()
			node.setDataValueInTS(column, GKTimeSerieIndex(tsDescription.getInterval(now)), cycle, 0.0, tsDescription)
	now = now.addSecs(interval.toSeconds()[0])

				
			

Beachten Sie, dass die Spalte mit GK.BuildContentserstellt wird, damit der richtige Datenursprung, in diesem Fall der ausgewählte Signalprogrammplan, gewählt wird.

Sind die Spalte und die Zeitreihenbeschreibung richtig definiert, erscheint die Zeitreihe im Dialog der signalisierten Knotenpunkts.

Bei Ausführung des Skripts für mehrere Signalprogrammpläne lassen sich mithilfe des Zeitreihenbetrachters schnell die jeweiligen Unterschiede erkennen, beispielsweise zwischen der Umlaufzeit an Wochentagen und Wochenenden.

  • Hast du eine Frage? Nimm Kontakt auf.
  • Hast du eine Frage? Nimm Kontakt auf.

TEILEN

Share on linkedin
Share on twitter
Share on email