-
Notifications
You must be signed in to change notification settings - Fork 0
/
analysis.py
156 lines (130 loc) · 8.15 KB
/
analysis.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import sqlite3
from trafficintelligence import moving
from trafficintelligence.storage import printDBError
import events
import toolkit
class Analysis:
def __init__(self, idx, world, seed, analysisZone=None, saveAllInteractions=False):
self.idx = idx
self.world = world
# self.interactions = world.completedInteractions
self.analysisZone = analysisZone
self.seed = seed
if saveAllInteractions:
self.interactions = world.completedInteractions + world.completedInteractions
else:
self.interactions = world.completedInteractions
def getIdx(self):
return self.idx
def save(self, filename):
toolkit.saveYaml(filename, self)
@staticmethod
def load(filename):
toolkit.loadYaml(filename)
def getAnalysisZoneArea(self):
if self.analysisZone is None:
return None
else:
return self.analysisZone.getArea()
def getInteractions(self):
return self.interactions
def saveIndicators(self, fileName):
self.saveIndicatorsToSqlite(fileName, self.getInteractions())
def saveParametersToTable(self, fileName):
connection = sqlite3.connect(fileName)
cursor = connection.cursor()
for ui in self.world.userInputs:
values = [self.idx, self.getAnalysisZoneArea(), ui.idx]
for distribution in ui.distributions:
dist = ui.distributions[distribution]
values.extend([dist.getType(), dist.getName(), dist.getLoc(), dist.getScale(), dist.getMinThreshold(), dist.getMaxThreshold(), dist.getCdf()])
query = "INSERT INTO analysis VALUES("+"?,"*len(values)
query = query[:-1]
query += ")"
cursor.execute(query, values)
connection.commit()
def saveIndicatorsToSqlite(self, filename, interactions, indicatorNames=events.Interaction.indicatorNames):
'Saves the indicator values in the table'
with sqlite3.connect(filename) as connection:
cursor = connection.cursor()
try:
self.createInteractionTable(cursor)
self.createIndicatorTable(cursor)
for inter in interactions:
self.saveInteraction(cursor, inter)
for indicatorName in indicatorNames:
indicator = inter.getIndicator(indicatorName)
if indicator is not None:
self.saveIndicator(cursor, inter.getNum(), indicator)
except sqlite3.OperationalError as error:
printDBError(error)
connection.commit()
def createInteractionTable(self, cursor):
cursor.execute('CREATE TABLE IF NOT EXISTS interactions (id INTEGER, analysis_id INTEGER, seed INTEGER, object_id1 INTEGER, object_id2 INTEGER, first_frame_number INTEGER, last_frame_number INTEGER, FOREIGN KEY(object_id1) REFERENCES objects(id), PRIMARY KEY(id, analysis_id, seed), FOREIGN KEY(object_id2) REFERENCES objects(id))')
def createIndicatorTable(self, cursor):
cursor.execute('CREATE TABLE IF NOT EXISTS indicators (interaction_id INTEGER, analysis_id INTEGER, seed INTEGER, indicator_type INTEGER, frame_number INTEGER, value REAL, FOREIGN KEY(interaction_id) REFERENCES interactions(id), PRIMARY KEY(interaction_id, analysis_id, seed, indicator_type, frame_number))')
def saveInteraction(self, cursor, interaction):
roadUserNumbers = list(interaction.getRoadUserNumbers())
# category = interaction.categoryNum
cursor.execute('INSERT INTO interactions VALUES({}, {}, {}, {}, {}, {}, {})'.format(interaction.getNum(), self.idx, self.seed, roadUserNumbers[0], roadUserNumbers[1], interaction.getFirstInstant(), interaction.getLastInstant()))
def saveIndicator(self, cursor, interactionNum, indicator):
for instant in indicator.getTimeInterval():
if indicator[instant]:
cursor.execute('INSERT INTO indicators VALUES({}, {}, {}, {}, {}, {})'.format(interactionNum, self.idx, self.seed, events.Interaction.indicatorNameToIndices[indicator.getName()], instant, indicator[instant]))
class AnalysisZone:
def __init__(self, intersection, area):
self.intersection = intersection # moving.Point
self.minAlignment = []
self.maxAlignment = []
self.area = area
for entryAlignment in intersection.entryAlignments:
self.minAlignment.append([entryAlignment.getTotalDistance() - self.area ** .5, entryAlignment.idx])
for exitAlignment in intersection.exitAlignments:
self.maxAlignment.append([self.area ** .5, exitAlignment.idx])
def getLimits(self):
"""return limits of analysis zone"""
return self.minAlignment, self.maxAlignment
def getArea(self):
"""returns area of analysis zone"""
return self.area
def getIntersection(self):
"""returns center of analysis zone"""
return self.intersection
def userInAnalysisZoneAtInstant(self, user, t):
"""determines if a user is inside a predetermined analysis zone"""
if t in list(user.timeInterval):
cp = user.getCurvilinearPositionAtInstant(t)
for minVal, maxVal in zip(self.minAlignment, self.maxAlignment):
if (minVal[0] <= cp[0] and cp[2] == minVal[1]) or (cp[0] <= maxVal[0] and cp[2] == maxVal[1]):
return True
return False
def positionInAnalysisZone(self, curvilinearPosition):
'''returns True if a curvilinear position is withing analysis zone bounds'''
for minVal, maxVal in zip(self.minAlignment, self.maxAlignment):
if (minVal[0] <= curvilinearPosition[0] and curvilinearPosition[2] == minVal[1]) or (curvilinearPosition[0] <= maxVal[0] and curvilinearPosition[2] == maxVal[1]):
return True
return False
def getUserIntervalInAnalysisZone(self, user):
'''returns the time interval at which user passed through analysis zone'''
firstInstant = None
lastInstant = None
for t in list(user.timeInterval):
if self.userInAnalysisZoneAtInstant(user, t):
firstInstant = t
break
if firstInstant is None:
return None
else:
for instant in range(firstInstant, user.getLastInstant() + 1):
if not self.userInAnalysisZoneAtInstant(user, instant):
lastInstant = instant - 1
break
if lastInstant is None:
lastInstant = user.getLastInstant()
return moving.TimeInterval(firstInstant, lastInstant)
def createAnalysisTable(fileName):
connection = sqlite3.connect(fileName)
cursor = connection.cursor()
tableName = 'analysis'
cursor.execute("CREATE TABLE IF NOT EXISTS " + tableName + " (analysis_id INTEGER, area REAL, userInput_id INTEGER, deltaDistribution_type TEXT, deltaDistribution_name TEXT, deltaDistribution_loc REAL, deltaDistribution_scale REAL, deltaDistribution_a REAL, deltaDistribution_b REAL, deltaDistribution_cdf LIST, headwayDistribution_type TEXT, headwayDistribution_name TEXT, headwayDistribution_loc REAL, headwayDistribution_scale REAL, headwayDistribution_a REAL, headwayDistribution_b REAL, headwayDistribution_cdf LIST, geometryDistribution_type TEXT, geometryDistribution_name TEXT, geometryDistribution_loc REAL, geometryDistribution_scale REAL, geometryDistribution_a REAL, geometryDistribution_b REAL, geometryDistribution_cdf LIST, speedDistribution_type TEXT, speedDistribution_name TEXT, speedDistribution_loc REAL, speedDistribution_scale REAL, speedDistribution_a REAL, speedDistribution_b REAL, speedDistribution_cdf LIST, tauDistribution_type TEXT, tauDistribution_name TEXT, tauDistribution_loc REAL, tauDistribution_scale REAL, tauDistribution_a REAL, tauDistribution_b REAL, tauDistribution_cdf LIST, criticalGapDistribution_type TEXT, criticalGapDistribution_name TEXT, criticalGapDistribution_loc REAL, criticalGapDistribution_scale REAL, criticalGapDistribution_a REAL, criticalGapDistribution_b REAL, criticalGapDistribution_cdf LIST, PRIMARY KEY(analysis_id, area, userInput_id))")
connection.commit()