Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Heatmap request examples #1899

63 changes: 62 additions & 1 deletion app/api/src/core/heatmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ def merge_heatmap_traveltime_objects(traveltimeobjs):


def sort_and_unique_by_grid_ids(grid_ids, travel_times):
"""
Sort grid_ids in order to do calculations on travel times faster.
Also find the uniques which used as ids (h3 index)
"""

table_ = np.vstack((grid_ids, travel_times))
table = table_.transpose()
sorted_table = table[table[:, 0].argsort()]
Expand All @@ -45,6 +50,18 @@ def sort_and_unique_by_grid_ids(grid_ids, travel_times):

@njit()
def medians(sorted_table, unique):
"""
Example:
sorted_table:
[[0,0,0,1,1,2,2,2,3,3,3,3],
[1,2,3,4,5,6,7,8,9,10,11,12]]
unique:
[0,1,2,3]
medians:
[2,5,7,10]

Consider unique is touples of (unique, index)
"""
if not sorted_table.size:
return None
travel_times = sorted_table.transpose()[1]
Expand All @@ -62,6 +79,19 @@ def medians(sorted_table, unique):

@njit()
def mins(sorted_table, unique):
"""
Example:
sorted_table:
[[0,0,0,1,1,2,2,2,3,3,3,3],
[1,2,3,4,5,6,7,8,9,10,11,12]]
unique:
[0,1,2,3]

mins:
[1,4,6,9]

Consider unique is touples of (unique, index)
"""
if not sorted_table.size:
return None
travel_times = sorted_table.transpose()[1]
Expand All @@ -78,6 +108,18 @@ def mins(sorted_table, unique):

@njit()
def counts(sorted_table, unique):
"""
Example:
sorted_table:
[[0,0,0,1,1,2,2,2,3,3,3,3],
[1,2,3,4,5,6,7,8,9,10,11,12]]
unique:
[0,1,2,3]
counts:
[3,2,3,4]

Consider unique is touples of (unique, index)
"""
if not sorted_table.size:
return None
travel_times = sorted_table.transpose()[1]
Expand All @@ -94,6 +136,18 @@ def counts(sorted_table, unique):

@njit()
def averages(sorted_table, unique):
"""
Example:
sorted_table:
[[0,0,0,1,1,2,2,2,3,3,3,3],
[1,2,3,4,5,6,7,8,9,10,11,12]]
unique:
[0,1,2,3]
averages:
[2,5,7,10]

Consider unique is touples of (unique, index)
"""
if not sorted_table.size:
return None
travel_times = sorted_table.transpose()[1]
Expand Down Expand Up @@ -142,6 +196,13 @@ def modified_gaussian_per_grid(sorted_table, unique, sensitivity, cutoff):


def quantile_classify(a, NQ=5):
"""
Classify the array into NQ quantiles.
examle:
a = np.array([0,0,0,1,1,2,2,2,3,3,3,3])
quantile is:
array([0,0,0,1,1,2,2,2,3,3,3,3])
"""
if a is None:
return None
if not a.size:
Expand All @@ -158,7 +219,7 @@ def quantile_classify(a, NQ=5):
np.logical_and(np.greater_equal(a, quantiles[i]), np.less(a, quantiles[i + 1]))
)
] = (i + 2)
out[np.isnan(a)] = -1
out[np.isnan(a)] = 0

return out

Expand Down
17 changes: 14 additions & 3 deletions app/api/src/core/heatmap_cython.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import h3
import numpy as np
import cython

def get_h3_parents(h3_array, resolution):
def get_h3_parents(h3_array: np.ndarray, int resolution):
"""Get the parent of each H3 index in the array at the given resolution.
"""

if h3_array is None:
return None
if not h3_array.size:
Expand All @@ -13,7 +16,10 @@ def get_h3_parents(h3_array, resolution):
return out


def create_grid_pointers(grids_unordered_map, parent_tags):
def create_grid_pointers(grids_unordered_map:dict, parent_tags:dict):
"""
Create grid pointers for each grid in the grid map.
"""
grid_pointers = {}
get_id = lambda tag: grids_unordered_map.get(tag, -1)
for key, parent_tag in parent_tags.items():
Expand All @@ -23,14 +29,19 @@ def create_grid_pointers(grids_unordered_map, parent_tags):
grid_pointers[key] = np.vectorize(get_id)(parent_tag)
return grid_pointers

def generate_final_geojson(grid_ids, polygons, calculations, quantiles):
def generate_final_geojson(grid_ids:np.ndarray, polygons:np.ndarray, calculations:dict, quantiles:dict, agg_classes:np.ndarray):
"""
Generate the final geojson.
"""

geojson = {}
features = []
for i, grid_id in enumerate(grid_ids):
feature = {
"type": "Feature",
"properties": {
"id": int(grid_id),
"agg_class": round(agg_classes[i], 2),
},
"geometry": {
"type": "Polygon",
Expand Down
Loading