api: Add histogram details to /mapdetails/road endpoint
This commit is contained in:
parent
2fd664f79a
commit
04bf99b7cb
|
@ -1,5 +1,6 @@
|
||||||
import json
|
import json
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
import logging
|
||||||
import numpy
|
import numpy
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ from obs.api.utils import round_to
|
||||||
round_distance = partial(round_to, multiples=0.001)
|
round_distance = partial(round_to, multiples=0.001)
|
||||||
round_speed = partial(round_to, multiples=0.1)
|
round_speed = partial(round_to, multiples=0.1)
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
def get_bearing(a, b):
|
def get_bearing(a, b):
|
||||||
# longitude, latitude
|
# longitude, latitude
|
||||||
|
@ -25,6 +27,8 @@ def get_bearing(a, b):
|
||||||
) * numpy.cos(dL)
|
) * numpy.cos(dL)
|
||||||
return numpy.arctan2(X, Y)
|
return numpy.arctan2(X, Y)
|
||||||
|
|
||||||
|
# Bins for histogram on overtaker distances. 0, 0.25, ... 2.25, infinity
|
||||||
|
DISTANCE_BINS = numpy.arange(0, 2.5, 0.25).tolist() + [float('inf')]
|
||||||
|
|
||||||
@api.route("/mapdetails/road", methods=["GET"])
|
@api.route("/mapdetails/road", methods=["GET"])
|
||||||
async def mapdetails_road(req):
|
async def mapdetails_road(req):
|
||||||
|
@ -88,16 +92,15 @@ async def mapdetails_road(req):
|
||||||
return arr[:, cond], arr[:, ~cond]
|
return arr[:, cond], arr[:, ~cond]
|
||||||
|
|
||||||
forwards, backwards = partition(data, ~mask)
|
forwards, backwards = partition(data, ~mask)
|
||||||
print("for", forwards.dtype, "back", backwards.dtype)
|
|
||||||
|
|
||||||
def array_stats(arr, rounder):
|
def array_stats(arr, rounder, bins=30):
|
||||||
if len(arr):
|
if len(arr):
|
||||||
print("ARR DTYPE", arr.dtype)
|
|
||||||
print("ARR", arr)
|
|
||||||
arr = arr[~numpy.isnan(arr)]
|
arr = arr[~numpy.isnan(arr)]
|
||||||
|
|
||||||
n = len(arr)
|
n = len(arr)
|
||||||
|
|
||||||
|
hist, bins = numpy.histogram(arr, bins=bins)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"statistics": {
|
"statistics": {
|
||||||
"count": n,
|
"count": n,
|
||||||
|
@ -106,6 +109,10 @@ async def mapdetails_road(req):
|
||||||
"max": rounder(numpy.max(arr)) if n else None,
|
"max": rounder(numpy.max(arr)) if n else None,
|
||||||
"median": rounder(numpy.median(arr)) if n else None,
|
"median": rounder(numpy.median(arr)) if n else None,
|
||||||
},
|
},
|
||||||
|
"histogram": {
|
||||||
|
"bins": [None if math.isinf(b) else b for b in bins.tolist()],
|
||||||
|
"counts": hist.tolist(),
|
||||||
|
},
|
||||||
"values": list(map(rounder, arr.tolist())),
|
"values": list(map(rounder, arr.tolist())),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,15 +125,13 @@ async def mapdetails_road(req):
|
||||||
# convert to degrees, as this is more natural to understand for consumers
|
# convert to degrees, as this is more natural to understand for consumers
|
||||||
bearing = round_to((bearing / math.pi * 180 + 360) % 360, 1)
|
bearing = round_to((bearing / math.pi * 180 + 360) % 360, 1)
|
||||||
|
|
||||||
print(road.geometry)
|
|
||||||
|
|
||||||
def get_direction_stats(direction_arrays, backwards=False):
|
def get_direction_stats(direction_arrays, backwards=False):
|
||||||
return {
|
return {
|
||||||
"bearing": ((bearing + 180) % 360 if backwards else bearing)
|
"bearing": ((bearing + 180) % 360 if backwards else bearing)
|
||||||
if bearing is not None
|
if bearing is not None
|
||||||
else None,
|
else None,
|
||||||
"distanceOvertaker": array_stats(direction_arrays[0], round_distance),
|
"distanceOvertaker": array_stats(direction_arrays[0], round_distance, bins=DISTANCE_BINS),
|
||||||
"distanceStationary": array_stats(direction_arrays[1], round_distance),
|
"distanceStationary": array_stats(direction_arrays[1], round_distance, bins=DISTANCE_BINS),
|
||||||
"speed": array_stats(direction_arrays[2], round_speed),
|
"speed": array_stats(direction_arrays[2], round_speed),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue