Commit 684d30e8 by Corey Koval

Performance Improvements

parent 2b83094a
...@@ -21,6 +21,7 @@ from multiprocessing import Process, Queue ...@@ -21,6 +21,7 @@ from multiprocessing import Process, Queue
from bottle import route, run, request, get, post, put, response, redirect, template, static_file from bottle import route, run, request, get, post, put, response, redirect, template, static_file
DBSCAN_Q = Queue() DBSCAN_Q = Queue()
DBSCAN_WAIT_Q = Queue()
DATABASE_EDIT_Q = Queue() DATABASE_EDIT_Q = Queue()
DATABASE_RETURN = Queue() DATABASE_RETURN = Queue()
...@@ -198,8 +199,11 @@ def plot_intersects(lat_a, lon_a, doa_a, lat_b, lon_b, doa_b, max_distance = 100 ...@@ -198,8 +199,11 @@ def plot_intersects(lat_a, lon_a, doa_a, lat_b, lon_b, doa_b, max_distance = 100
# This becomes noticable at over 10k intersections. # This becomes noticable at over 10k intersections.
####################################################################### #######################################################################
def do_dbscan(X): def do_dbscan(X):
DBSCAN_WAIT_Q.put(True)
db = DBSCAN(eps=ms.eps, min_samples=ms.min_samp).fit(X) db = DBSCAN(eps=ms.eps, min_samples=ms.min_samp).fit(X)
DBSCAN_Q.put(db.labels_) DBSCAN_Q.put(db.labels_)
if not DBSCAN_WAIT_Q.empty():
DBSCAN_WAIT_Q.get()
############################################### ###############################################
# Computes DBSCAN Alorithm is applicable, # Computes DBSCAN Alorithm is applicable,
...@@ -222,7 +226,7 @@ def process_data(database_name): ...@@ -222,7 +226,7 @@ def process_data(database_name):
for aoi in aoi_list: for aoi in aoi_list:
print(f"Checking AOI {aoi}.") print(f"Checking AOI {aoi}.")
curs.execute('''SELECT longitude, latitude, time FROM intersects curs.execute('''SELECT longitude, latitude, time FROM intersects
WHERE aoi_id=? ORDER BY confidence LIMIT 50000''', [aoi]) WHERE aoi_id=? ORDER BY confidence LIMIT 25000''', [aoi])
intersect_array = np.array(curs.fetchall()) intersect_array = np.array(curs.fetchall())
if intersect_array.size != 0: if intersect_array.size != 0:
if ms.eps > 0: if ms.eps > 0:
...@@ -231,12 +235,23 @@ def process_data(database_name): ...@@ -231,12 +235,23 @@ def process_data(database_name):
size_x = sys.getsizeof(X)/1024 size_x = sys.getsizeof(X)/1024
print(f"The dataset is {size_x} kilobytes") print(f"The dataset is {size_x} kilobytes")
print(f"Computing Clusters from {n_points} intersections.") print(f"Computing Clusters from {n_points} intersections.")
while not DBSCAN_WAIT_Q.empty():
print("Waiting for my turn...")
time.sleep(1)
starttime = time.time() starttime = time.time()
db = Process(target=do_dbscan,args=(X,)) db = Process(target=do_dbscan,args=(X,))
db.daemon = True
db.start() db.start()
labels = DBSCAN_Q.get() try:
labels = DBSCAN_Q.get(timeout=10)
db.join() db.join()
except:
print("DBSCAN took took long, terminated.")
if not DBSCAN_WAIT_Q.empty():
DBSCAN_WAIT_Q.get()
db.terminate()
return likely_location, intersect_list, ellipsedata
stoptime = time.time() stoptime = time.time()
print(f"DBSCAN took {stoptime - starttime} seconds to compute the clusters.") print(f"DBSCAN took {stoptime - starttime} seconds to compute the clusters.")
...@@ -289,7 +304,7 @@ def process_data(database_name): ...@@ -289,7 +304,7 @@ def process_data(database_name):
intersect_list.append(x.tolist()) intersect_list.append(x.tolist())
else: else:
print("No Intersections.") print(f"No Intersections in AOI {aoi}.")
conn.close() conn.close()
return likely_location, intersect_list, ellipsedata return likely_location, intersect_list, ellipsedata
...@@ -311,12 +326,12 @@ def purge_database(type, lat, lon, radius): ...@@ -311,12 +326,12 @@ def purge_database(type, lat, lon, radius):
distance = v.inverse(x, (lat, lon))[0] distance = v.inverse(x, (lat, lon))[0]
if distance < radius: if distance < radius:
command = "DELETE FROM intersects WHERE latitude=? AND longitude=?" command = "DELETE FROM intersects WHERE latitude=? AND longitude=?"
DATABASE_EDIT_Q.put((command, x)) DATABASE_EDIT_Q.put((command, x, False))
DATABASE_RETURN.get(timeout=1) # DATABASE_RETURN.get(timeout=1)
purge_count += 1 purge_count += 1
elif type == "aoi": elif type == "aoi":
pass pass
DATABASE_EDIT_Q.put(("done", None)) DATABASE_EDIT_Q.put(("done", None, False))
print(f"I purged {purge_count} intersects.") print(f"I purged {purge_count} intersects.")
@get("/run_all_aoi_rules") @get("/run_all_aoi_rules")
...@@ -334,31 +349,31 @@ def run_aoi_rules(): ...@@ -334,31 +349,31 @@ def run_aoi_rules():
conn.close() conn.close()
if n_aoi == 0: if n_aoi == 0:
command = "UPDATE intersects SET aoi_id=?" command = "UPDATE intersects SET aoi_id=?"
DATABASE_EDIT_Q.put((command, (-1,))) DATABASE_EDIT_Q.put((command, (-1,), True))
DATABASE_EDIT_Q.put(("done", None)) DATABASE_EDIT_Q.put(("done", None, False))
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
else: else:
for point in intersect_list: for point in intersect_list:
keep_list = [] keep_list = []
lat, lon = point lat, lon = point
for x in aoi_list: for x in aoi_list:
aoi = { # aoi = {
'uid': x[0], # 'uid': x[0],
'aoi_type': x[1], # 'aoi_type': x[1],
'latitude': x[2], # 'latitude': x[2],
'longitude': x[3], # 'longitude': x[3],
'radius': x[4] # 'radius': x[4]
} # }
distance = v.inverse((aoi['latitude'], aoi['longitude']), (lat, lon))[0] distance = v.haversine(x[2], x[3], lat, lon)
if aoi['aoi_type'] == "exclusion": if x[1] == "exclusion":
if distance < aoi['radius']: if distance < x[4]:
keep_list = [False] keep_list = [False]
break break
elif aoi['aoi_type'] == "aoi": elif x[1] == "aoi":
if distance < aoi['radius']: if distance < x[4]:
command = "UPDATE intersects SET aoi_id=? WHERE latitude=? AND longitude=?" command = "UPDATE intersects SET aoi_id=? WHERE latitude=? AND longitude=?"
params = (aoi['uid'], lat, lon) params = (x[0], lat, lon)
DATABASE_EDIT_Q.put((command, params)) DATABASE_EDIT_Q.put((command, params, True))
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
sorted += 1 sorted += 1
keep_list.append(True) keep_list.append(True)
...@@ -367,11 +382,11 @@ def run_aoi_rules(): ...@@ -367,11 +382,11 @@ def run_aoi_rules():
if not any(keep_list): if not any(keep_list):
command = "DELETE from intersects WHERE latitude=? AND longitude=?" command = "DELETE from intersects WHERE latitude=? AND longitude=?"
DATABASE_EDIT_Q.put((command, point)) DATABASE_EDIT_Q.put((command, point, True))
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
purged += 1 purged += 1
DATABASE_EDIT_Q.put(("done", None)) DATABASE_EDIT_Q.put(("done", None, False))
print(f"Purged {purged} intersections and sorted {sorted} intersections into {n_aoi} AOIs.") print(f"Purged {purged} intersections and sorted {sorted} intersections into {n_aoi} AOIs.")
return "OK" return "OK"
...@@ -456,6 +471,8 @@ def write_czml(best_point, all_the_points, ellipsedata): ...@@ -456,6 +471,8 @@ def write_czml(best_point, all_the_points, ellipsedata):
for x in ellipsedata: for x in ellipsedata:
# rotation = 2 * np.pi - x[2] # rotation = 2 * np.pi - x[2]
if x[0] >= x[1]: if x[0] >= x[1]:
# rotation = x[2]
semiMajorAxis = x[0] semiMajorAxis = x[0]
semiMinorAxis = x[1] semiMinorAxis = x[1]
rotation = 2 * np.pi - x[2] rotation = 2 * np.pi - x[2]
...@@ -690,7 +707,11 @@ def update_rx(action): ...@@ -690,7 +707,11 @@ def update_rx(action):
add_receiver(receiver_url) add_receiver(receiver_url)
elif action == "del": elif action == "del":
index = int(data['uid']) index = int(data['uid'])
del_receiver(receivers[index].station_id) command = "DELETE FROM receivers WHERE station_id=?"
DATABASE_EDIT_Q.put((command, [int(data['uid'])], True))
DATABASE_RETURN.get(timeout=1)
DATABASE_EDIT_Q.put(("done", None, False))
# del_receiver(receivers[index].station_id)
del receivers[index] del receivers[index]
elif action == "activate": elif action == "activate":
index = int(data['uid']) index = int(data['uid'])
...@@ -743,13 +764,13 @@ def handle_interest_areas(action): ...@@ -743,13 +764,13 @@ def handle_interest_areas(action):
add_aoi(aoi_type, lat, lon, radius) add_aoi(aoi_type, lat, lon, radius)
elif action == "del": elif action == "del":
command = "UPDATE intersects SET aoi_id=? WHERE aoi_id=?" command = "UPDATE intersects SET aoi_id=? WHERE aoi_id=?"
DATABASE_EDIT_Q.put((command, (-1,data['uid']))) DATABASE_EDIT_Q.put((command, (-1, data['uid']), True))
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
to_table = str(data['uid']) to_table = str(data['uid'])
command = "DELETE FROM interest_areas WHERE uid=?" command = "DELETE FROM interest_areas WHERE uid=?"
DATABASE_EDIT_Q.put((command, to_table)) DATABASE_EDIT_Q.put((command, to_table, True))
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
DATABASE_EDIT_Q.put(("done", None)) DATABASE_EDIT_Q.put(("done", None, False))
elif action == "purge": elif action == "purge":
conn = sqlite3.connect(database_name) conn = sqlite3.connect(database_name)
c = conn.cursor() c = conn.cursor()
...@@ -811,7 +832,7 @@ def run_receiver(receivers): ...@@ -811,7 +832,7 @@ def run_receiver(receivers):
if keep: if keep:
to_table = [receivers[x].doa_time, avg_coord[0], avg_coord[1], len(intersect_list), avg_coord[2], in_aoi] to_table = [receivers[x].doa_time, avg_coord[0], avg_coord[1], len(intersect_list), avg_coord[2], in_aoi]
command = "INSERT INTO intersects VALUES (?,?,?,?,?,?)" command = "INSERT INTO intersects VALUES (?,?,?,?,?,?)"
DATABASE_EDIT_Q.put((command, to_table)) DATABASE_EDIT_Q.put((command, to_table, True))
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
# Loop to compute intersections for a single receiver and update all receivers # Loop to compute intersections for a single receiver and update all receivers
...@@ -831,6 +852,7 @@ def run_receiver(receivers): ...@@ -831,6 +852,7 @@ def run_receiver(receivers):
lon_rxa = current_doa[3] lon_rxa = current_doa[3]
conf_rxa = current_doa[4] conf_rxa = current_doa[4]
doa_rxa = current_doa[5] doa_rxa = current_doa[5]
keep_count = 0
if len(lob_array) > 1: if len(lob_array) > 1:
for previous in lob_array: for previous in lob_array:
lat_rxb = previous[0] lat_rxb = previous[0]
...@@ -850,17 +872,19 @@ def run_receiver(receivers): ...@@ -850,17 +872,19 @@ def run_receiver(receivers):
# if intersection: # if intersection:
keep, in_aoi = check_aoi(*intersection[0:2]) keep, in_aoi = check_aoi(*intersection[0:2])
if keep: if keep:
print(intersection) # print(intersection)
keep_count += 1
to_table = [current_time, intersection[0], intersection[1], 1, intersection[2], in_aoi] to_table = [current_time, intersection[0], intersection[1], 1, intersection[2], in_aoi]
command = "INSERT INTO intersects VALUES (?,?,?,?,?,?)" command = "INSERT INTO intersects VALUES (?,?,?,?,?,?)"
DATABASE_EDIT_Q.put((command, to_table)) DATABASE_EDIT_Q.put((command, to_table, True))
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
print(f"Computed and kept {keep_count} intersections.")
command = "INSERT INTO lobs VALUES (?,?,?,?,?,?)" command = "INSERT INTO lobs VALUES (?,?,?,?,?,?)"
DATABASE_EDIT_Q.put((command, current_doa)) DATABASE_EDIT_Q.put((command, current_doa, True))
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
DATABASE_EDIT_Q.put(("done", None)) DATABASE_EDIT_Q.put(("done", None, False))
try: try:
if rx.isActive: rx.update() if rx.isActive: rx.update()
except IOError: except IOError:
...@@ -898,7 +922,7 @@ def check_aoi(lat, lon): ...@@ -898,7 +922,7 @@ def check_aoi(lat, lon):
'longitude': x[3], 'longitude': x[3],
'radius': x[4] 'radius': x[4]
} }
distance = v.inverse((aoi['latitude'], aoi['longitude']), (lat, lon))[0] distance = v.haversine(aoi['latitude'], aoi['longitude'], lat, lon)
if aoi['aoi_type'] == "exclusion": if aoi['aoi_type'] == "exclusion":
if distance < aoi['radius']: if distance < aoi['radius']:
keep = False keep = False
...@@ -930,9 +954,9 @@ def add_receiver(receiver_url): ...@@ -930,9 +954,9 @@ def add_receiver(receiver_url):
new_rx['mobile'],new_rx['single'], new_rx['latitude'], new_rx['longitude']] new_rx['mobile'],new_rx['single'], new_rx['latitude'], new_rx['longitude']]
command = "INSERT OR IGNORE INTO receivers VALUES (?,?,?,?,?,?,?)" command = "INSERT OR IGNORE INTO receivers VALUES (?,?,?,?,?,?,?)"
DATABASE_EDIT_Q.put((command, to_table)) DATABASE_EDIT_Q.put((command, to_table, True))
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
DATABASE_EDIT_Q.put(("done", None)) DATABASE_EDIT_Q.put(("done", None, False))
mobile = c.execute("SELECT isMobile FROM receivers WHERE station_id = ?", mobile = c.execute("SELECT isMobile FROM receivers WHERE station_id = ?",
[new_rx['station_id']]).fetchone()[0] [new_rx['station_id']]).fetchone()[0]
single = c.execute("SELECT isSingle FROM receivers WHERE station_id = ?", single = c.execute("SELECT isSingle FROM receivers WHERE station_id = ?",
...@@ -977,22 +1001,12 @@ def update_rx_table(): ...@@ -977,22 +1001,12 @@ def update_rx_table():
latitude=?, latitude=?,
longitude=? longitude=?
WHERE station_id = ?''' WHERE station_id = ?'''
DATABASE_EDIT_Q.put((command, to_table)) DATABASE_EDIT_Q.put((command, to_table, True))
# try: # try:
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
# except: # except:
# pass # pass
DATABASE_EDIT_Q.put(("done", None)) DATABASE_EDIT_Q.put(("done", None, False))
###############################################
# Removes a receiver from the program and
# database upon request.
###############################################
def del_receiver(del_rx):
command = "DELETE FROM receivers WHERE station_id=?"
DATABASE_EDIT_Q.put((command, [del_rx]))
DATABASE_RETURN.get(timeout=1)
DATABASE_EDIT_Q.put(("done", None))
############################################### ###############################################
# Updates the database with new interest areas. # Updates the database with new interest areas.
...@@ -1006,9 +1020,9 @@ def add_aoi(aoi_type, lat, lon, radius): ...@@ -1006,9 +1020,9 @@ def add_aoi(aoi_type, lat, lon, radius):
uid = (prev_uid + 1) if prev_uid != None else 0 uid = (prev_uid + 1) if prev_uid != None else 0
to_table = [uid, aoi_type, lat, lon, radius] to_table = [uid, aoi_type, lat, lon, radius]
command = 'INSERT INTO interest_areas VALUES (?,?,?,?,?)' command = 'INSERT INTO interest_areas VALUES (?,?,?,?,?)'
DATABASE_EDIT_Q.put((command, to_table)) DATABASE_EDIT_Q.put((command, to_table, True))
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
DATABASE_EDIT_Q.put(("done", None)) DATABASE_EDIT_Q.put(("done", None, False))
######################################### #########################################
# Read all the AOIs from the DB # Read all the AOIs from the DB
...@@ -1021,6 +1035,10 @@ def fetch_aoi_data(): ...@@ -1021,6 +1035,10 @@ def fetch_aoi_data():
conn.close() conn.close()
return aoi_list return aoi_list
###############################################
# One thread responsible for all database write
# operations.
###############################################
def database_writer(): def database_writer():
conn = sqlite3.connect(database_name) conn = sqlite3.connect(database_name)
c = conn.cursor() c = conn.cursor()
...@@ -1055,16 +1073,18 @@ def database_writer(): ...@@ -1055,16 +1073,18 @@ def database_writer():
lob REAL)''') lob REAL)''')
conn.commit() conn.commit()
while True: while True:
command, items = DATABASE_EDIT_Q.get() command, items, reply = DATABASE_EDIT_Q.get()
if command == "done": if command == "done":
conn.commit() conn.commit()
elif command == "close": elif command == "close":
conn.commit() conn.commit()
conn.close() conn.close()
if reply:
DATABASE_RETURN.put(True) DATABASE_RETURN.put(True)
break break
else: else:
c.execute(command, items) c.execute(command, items)
if reply:
DATABASE_RETURN.put(True) DATABASE_RETURN.put(True)
############################################### ###############################################
...@@ -1075,7 +1095,7 @@ def finish(): ...@@ -1075,7 +1095,7 @@ def finish():
print("Processing, please wait.") print("Processing, please wait.")
ms.receiving = False ms.receiving = False
update_rx_table() update_rx_table()
DATABASE_EDIT_Q.put(("close", None)) DATABASE_EDIT_Q.put(("close", None, True))
DATABASE_RETURN.get(timeout=1) DATABASE_RETURN.get(timeout=1)
if geofile != None: if geofile != None:
write_geojson(*process_data(database_name)[:2]) write_geojson(*process_data(database_name)[:2])
......
...@@ -15,7 +15,7 @@ from math import atan2 ...@@ -15,7 +15,7 @@ from math import atan2
from math import cos from math import cos
from math import radians from math import radians
from math import degrees from math import degrees
from math import sin from math import sin, asin
from math import sqrt from math import sqrt
from math import tan from math import tan
from math import pow from math import pow
...@@ -24,6 +24,16 @@ a=6378137.0 # radius at equator in meters (WGS-84) ...@@ -24,6 +24,16 @@ a=6378137.0 # radius at equator in meters (WGS-84)
f=1/298.257223563 # flattening of the ellipsoid (WGS-84) f=1/298.257223563 # flattening of the ellipsoid (WGS-84)
b=(1-f)*a b=(1-f)*a
def haversine(lat1, lon1, lat2, lon2):
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
c = 2 * asin(sqrt(sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2))
return c * a
def get_heading(coord1, coord2): def get_heading(coord1, coord2):
lat1 = radians(coord1[0]) lat1 = radians(coord1[0])
lon1 = radians(coord1[1]) lon1 = radians(coord1[1])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment