-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtrajectory.py
More file actions
247 lines (225 loc) · 10 KB
/
trajectory.py
File metadata and controls
247 lines (225 loc) · 10 KB
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#!/usr/bin/env python
from datetime import datetime
from compute import haversine
# Calculate Haversine distance between subsequent points
def haversineDistance(lon, lat): # pass the lists with coordinates (longitude and latitude)
haversineDistance = []
for i in range(1, len(lat)):
haversineDistance.append(haversine(lat[i - 1], lat[i], lon[i - 1], lon[i]))
return haversineDistance
# Add points to the connected components (on both sides), it stops when it finds a local maxima
def increaseCC(cc, maxi, mini,
distances): # pass: list of connected components lists, list of maxima, list of minima, list of distances
for i in range(0, len(cc) - 1):
if i == 0:
while cc[i][2] not in maxi and cc[i][2] < cc[i + 1][0]:
if cc[i][0] > 0 and cc[i][2] < len(distances) - 1: # Excluding the first and last indexes
if (distances[cc[i][0] - 1] > distances[cc[i][2] + 1]):
cc[i][0] -= 1
else:
cc[i][2] += 1
elif cc[i][0] == 0:
cc[i][2] += 1
elif cc[i][2] == len(distances) - 1:
cc[i][0] -= 1
elif i > 0 and i < len(cc) - 1:
while (cc[i][0] not in maxi) and (cc[i][2] not in maxi) and cc[i][2] < cc[i + 1][0] and cc[i][0] > \
cc[i - 1][2]:
if cc[i][0] > 0 and cc[i][2] < len(distances) - 1: # Excluding the fist and last indexes
if (distances[cc[i][0] - 1] > distances[cc[i][2] + 1]):
cc[i][0] -= 1
else:
cc[i][2] += 1
elif cc[i][0] == 0:
cc[i][2] += 1
elif cc[i][2] == len(distances) - 1:
cc[i][0] -= 1
while (cc[len(cc) - 1][0] not in maxi) and cc[len(cc) - 1][0] != cc[len(cc) - 2][2]:
cc[len(cc) - 1][0] -= 1
return cc
# Joins connected components when they share a local maxima and also returns the bars (ranges) identified
def joinCC(cc, distances):
barTemp = []
keep = []
copycc = cc[:] # making a copy of cc to record all the changes
joined = [] # keeping track of the joined cc
for i in range(len(cc) - 1):
if cc[i][2] == cc[i + 1][0] and i not in joined:
if distances[cc[i][1]] > distances[cc[i + 1][1]]:
barTemp.append(cc[i]) # append the non-surviving cc to the list of bars
copycc[i + 1][0] = cc[i][0] # change value of the last point of the cc that remains
if (i + 1) not in keep:
keep.append(i + 1) # saving the one that should stay-contrary to the one that should be deleted
joined.append(i)
joined.append(i + 1)
else:
barTemp.append(cc[i + 1]) # append the non-surviving cc to the list of bars
copycc[i][2] = cc[i + 1][2] # change value of the first point of the cc that remains
if i not in keep:
keep.append(i) # saving the one that should stay-contrary to the one that should be deleted
joined.append(i)
joined.append(i + 1)
elif i not in joined:
# it is giving them two chances to survive and it is eliminating the last one automatically if it does not win
if i not in keep:
keep.append(i)
if len(cc) - 1 not in joined:
keep.append(len(cc) - 1)
newCC = [copycc[i] for i in keep]
return barTemp, newCC # return the identified bars and the list of new connectec components
def gpsSimplification(lon, lat, stamps, beta):
distances = haversineDistance(lon, lat) # obtain list with distances between points
mini = [] # list of local minima
maxi = [] # list of local maxima
# get local minima and local maxima
for i in range(2, len(distances) - 1):
if distances[i - 1] < distances[i] > distances[i + 1]:
maxi.append(i)
elif (distances[i - 1] > distances[i] < distances[i + 1]) or (
distances[i - 1] == distances[i] < distances[i + 1]) or (
distances[i - 1] > distances[i] == distances[i + 1]):
mini.append(i)
bar = [] # list of bars detected
cc = [] # list of connected components
for i in mini:
cc.append([i, i, i])
# while there is more than one connected component keep joining component together
while (len(cc) > 1):
cc = increaseCC(cc, maxi, mini, distances)
barTemporary, cc = joinCC(cc, distances)
bar.extend(barTemporary)
# beta simplification
newBar = []
for i in range(len(bar)):
if (abs(distances[bar[i][0]] - distances[bar[i][2]]) > beta):
newBar.append(bar[i])
# extracting all values from list // values is a list with other lists inside
valuesTemp = []
for i in newBar:
for j in i:
if (j not in valuesTemp):
valuesTemp.append(j)
# deleting equal values
valuesTemp2 = []
for i in range(1, len(valuesTemp)):
if distances[valuesTemp[i]] != distances[valuesTemp[i - 1]]:
valuesTemp2.append(valuesTemp[i])
# copying only remaining points
finalValues = []
for i in range(len(distances)):
if (i in valuesTemp2):
finalValues.append(distances[i])
else:
finalValues.append(None)
# obtaining plottable points
xplottable = []
plottable = []
for i in range(len(finalValues)):
if finalValues[i] is not None:
xplottable.append(i)
plottable.append(finalValues[i])
newLat = []
newLon = []
newStamp = []
newLon.append(lon[0])
newLat.append(lat[0])
newStamp.append(stamps[0])
for i in range(len(xplottable)):
newLat.append(lat[xplottable[i] + 1])
newLon.append(lon[xplottable[i] + 1])
newStamp.append(stamps[xplottable[i] + 1])
if (lon[-1] not in newLon):
newLon.append(lon[-1])
newLat.append(lat[-1])
newStamp.append(stamps[-1])
return newLon, newLat, newStamp
def totalDistance(dist):
d = 0.0
for i in range(len(dist)):
d += dist[i]
return d
def trajectoryClean(dbc, imei, beta, syear, smonth, sday):
curDate = datetime(syear, smonth, sday, 0, 0, 0)
endDate = datetime(syear, smonth, sday, 23, 59, 59)
tripStartTimes = []
tripEndTimes = []
ids = []
isAccurateList = []
comments = []
query = "select start_time, end_time, id, isAccurate, comments from trip{0} where start_time >= \"{1}\" and start_time <= \"{2}\"".format(
imei, curDate, endDate)
for record in dbc.SQLSelectGenerator(query):
tripStartTimes.append(record[0])
tripEndTimes.append(record[1])
ids.append(record[2])
isAccurateList.append(record[3])
if record[4] is not None:
comments.append(record[4])
else:
comments.append("")
newLon, newLat, startStr, endStr, dist, totalTime, stampsStr = get_trajectory_information(dbc, imei, beta,
tripStartTimes,
tripEndTimes)
return newLon, newLat, startStr, endStr, dist, totalTime, stampsStr, ids, isAccurateList, comments
def get_trajectory_information(dbc, imei, beta, tripStartTimes, tripEndTimes):
newLon = []
newLat = []
newStamp = []
if len(tripStartTimes) > 0:
# obtaining the data about all trips and then copying it to the arrays containing this information
for tripNumber in range(len(tripStartTimes)):
lat = []
lon = []
stamps = []
tempLon = []
tempLat = []
tempStamp = []
stmt = "select stamp, LatGPS, LongGPS from imei{0} where stamp >= \"{1}\" and stamp <= \"{2}\" and latgps is not null and longgps is not null and latgps!= 0 and longgps!=0 order by stamp;".format(
imei, tripStartTimes[tripNumber], tripEndTimes[tripNumber])
for l in dbc.SQLSelectGenerator(stmt):
stamps.append(l[0])
lat.append(l[1])
lon.append(l[2])
if len(lat) > 0 and len(lat) > 0:
tempLon, tempLat, tempStamp = gpsSimplification(lon, lat, stamps, beta)
newLon.append(tempLon)
newLat.append(tempLat)
newStamp.append(tempStamp)
else:
newLon.append(None)
newLat.append(None)
newStamp.append(None)
dist = []
for i in range(len(newLon)):
if newLon[i] is not None and newLat[i] is not None:
dist.append(totalDistance(haversineDistance(newLon[i], newLat[i])))
else:
dist.append(None)
# calculating total time of every trip detected
totalTime = []
for i in range(len(tripStartTimes)):
totalTime.append((tripEndTimes[i] - tripStartTimes[i]).total_seconds() / 60)
# converting start and end times to string to put them in json format
startStr = []
endStr = []
for i in range(len(tripEndTimes)):
startStr.append(tripStartTimes[i].strftime('%H:%M'))
endStr.append(tripEndTimes[i].strftime('%H:%M'))
# converting stamps to string to put them in json format
stampsStr = []
for i in range(len(newStamp)):
tempStampStr = []
if newStamp[i] is not None:
for j in range(len(newStamp[i])):
tempStampStr.append(newStamp[i][j].strftime('%H:%M:%S'))
stampsStr.append(tempStampStr)
return newLon, newLat, startStr, endStr, dist, totalTime, stampsStr
else:
newLon = []
newLat = []
startStr = []
endStr = []
dist = []
totalTime = []
stampsStr = []
return newLon, newLat, startStr, endStr, dist, totalTime, stampsStr