-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCreateResolutionMap.py
More file actions
225 lines (173 loc) · 7.35 KB
/
CreateResolutionMap.py
File metadata and controls
225 lines (173 loc) · 7.35 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
'''
@author: Max Felius
@date: 30/09/2020
Script to create a resolution map. It will combine datasets and count the amount of points per pre-defined cell
'''
#imports
import numpy as np
import os
import sys
import time
import pandas as pd
from scipy import spatial
import progressbar
#import custom class
import rijksdriehoek
#main class
class create_resolution_map:
def __init__(self,filename,resolution,filename_inter_data='combined_points.csv',use_intermediate_results=True):
'''
Initiate class
filename should be a string or a list. filename should be the absolute path of the file
:type filename: string/list[]
:type resolution: int
:rtype: None
'''
#Object variables
self.filename = filename
self.header = ['pnt_lon','pnt_lat','pnt_rdx','pnt_rdy']
self.data = None
self.xrange = None
self.yrange = None
self.xv = None
self.yv = None
self.radius = None
self.kdtree = None
self.cell_radius = resolution/2
self.grid_counter = None
self.grid_polygon = []
self.use_intermediate_results = use_intermediate_results
self.save_data = filename_inter_data
def start(self):
'''
method to start the processing steps
'''
#1. load data
self.data = self.Load_Data() #only columns for the rd_x and rd_y are returned
#2. create evaluation grid
self.Create_Grid()
#3. Create KD-Tree
self.kdtree = self.Create_KDTree()
#4. Compute number of points per grid
self.Count_Points()
#5. Save the results to a good output
return self.Create_df()
def Load_Data(self):
'''
Method for loading the data
'''
#check if the intermediate file already exists
if not self.use_intermediate_results:
if isinstance(self.filename,list):
data = pd.DataFrame(columns=self.header)
#for file_in in self.filename:
#TEST: progressbar
print('\nStarted reading the data...')
for i in progressbar.progressbar(range(len(self.filename))):
file_in = self.filename[i]
temp = pd.read_csv(file_in)
if 'pnt_rdx' not in list(temp) or 'pnt_rdy' not in list(temp):
#creating the rd coordinates using lat/lon as input
rd = rijksdriehoek.Rijksdriehoek()
rd.from_wgs(temp['pnt_lat'],temp['pnt_lon'])
#create new dataframe swith rd coordinates
df = pd.DataFrame(np.array([rd.rd_x,rd.rd_y]).T,columns=['pnt_rdx','pnt_rdy'])
temp = temp.join(df)
data = data.append(temp[self.header], ignore_index=True)
else:
data = data.append(temp[self.header], ignore_index=True)
print(f'\nAppended {file_in} to the dataset')
else:
data = pd.read_csv(self.filename)
# save intermediate results such that the datasets don't have to be combined every new run
if not os.path.isdir('intermediate_data'):
os.mkdir('intermediate_data')
data[self.header].to_csv(os.path.join('intermediate_data',self.save_data))
return data
else:
print(f'Reading pre-computed data {self.save_data}')
return pd.read_csv(os.path.join('intermediate_data',self.save_data))
def Create_Grid(self):
'''
create grid
'''
max_x = max(self.data['pnt_rdx'])
min_x = min(self.data['pnt_rdx'])
max_y = max(self.data['pnt_rdy'])
min_y = min(self.data['pnt_rdy'])
resolution = self.cell_radius
self.xrange = np.arange(min_x+resolution,max_x,resolution*2)
self.yrange = np.arange(min_y+resolution,max_y,resolution*2)
self.xv, self.yv = np.meshgrid(self.xrange,self.yrange)
def Create_KDTree(self):
'''
Init the kdtree
'''
return spatial.cKDTree(self.data[['pnt_rdx','pnt_rdy']].values) #input is an array
def Count_Points(self):
'''
Compute the grid cell
'''
#time keeping
start = time.time()
#A cell is a square. From the center to a corner the radius should be multiplied by sqrt(2).
#The search radius is made 1% larger just in case.
radius = np.sqrt(2)*self.cell_radius*1.01
grid_counter = np.zeros((len(self.yrange),len(self.xrange)))
print('Started counting points per cell...')
idx_y = 0
idx_x = 0
for idx in progressbar.progressbar(range(len(self.yrange)*len(self.xrange))):
#update idx_y and yrange if needed
if idx == idx_y*len(self.xrange):
y = self.yrange[idx_y]
idx_y += 1
#update idx_x and xrange if needed
if idx == 0:
pass
else:
idx_x += 1
if idx % len(self.xrange) == 0:
idx_x = 0
x = self.xrange[idx_x]
subset = self.kdtree.query_ball_point([x,y],r=radius)
if not subset:
pass
else:
values = np.array(self.data[['pnt_rdx','pnt_rdy']].iloc[subset].values)
rdx = values[:,0]
rdy = values[:,1]
#created a function so it can potentially be accelerated by using a GPU (not implemented)
def counter(rdx_in,rdy_in,cell_radius,x,y):
count = 0
for rdx,rdy in zip(rdx_in,rdy_in):
if x-cell_radius < rdx and x+cell_radius > rdx and y-cell_radius < rdy and y+cell_radius > rdy:
count += 1
return count
count = counter(rdx,rdy,self.cell_radius,x,y)
grid_counter[idx_y-1,idx_x] = count
#create the square polygon
lbrd = rijksdriehoek.Rijksdriehoek(x-self.cell_radius,y-self.cell_radius)
rbrd = rijksdriehoek.Rijksdriehoek(x+self.cell_radius,y-self.cell_radius)
rtrd = rijksdriehoek.Rijksdriehoek(x+self.cell_radius,y+self.cell_radius)
ltrd = rijksdriehoek.Rijksdriehoek(x-self.cell_radius,y+self.cell_radius)
leftbot = lbrd.to_wgs()
rightbot = rbrd.to_wgs()
righttop = rtrd.to_wgs()
lefttop = ltrd.to_wgs()
self.grid_polygon.append(f'POLYGON (({leftbot[1]} {leftbot[0]},{rightbot[1]} {rightbot[0]},{righttop[1]} {righttop[0]},{lefttop[1]} {lefttop[0]}))')
self.grid_counter = grid_counter
print(f'Elapsed time is {time.time()-start} seconds...')
def Create_df(self):
'''
Output a dataframe that can be saved
'''
X = np.ravel(self.xv)
Y = np.ravel(self.yv)
Z = np.ravel(self.grid_counter)
rd = rijksdriehoek.Rijksdriehoek(X,Y)
wgs = np.array(rd.to_wgs()).T
lat = wgs[:,0]
lon = wgs[:,1]
data_out = np.array([X,Y,lon,lat,Z,self.grid_polygon])
return pd.DataFrame(data_out.T,columns=['rd_x','rd_y','lon','lat','Counts','wkt'])