from io import BytesIO
from pathlib import Path
import numpy as np
import requests
from arro3.core import ChunkedArray, fixed_size_list_array
from arro3.io import read_parquet
from geoarrow.rust.core import ChunkedGeometryArray, centroid, from_wkt
from ipywidgets import FloatRangeSlider, jsdlink
from lonboard import Map, ScatterplotLayer
from lonboard.colormap import apply_continuous_cmap
from lonboard.controls import MultiRangeSlider
from lonboard.layer_extension import DataFilterExtension
from palettable.colorbrewer.diverging import BrBG_10
from pyodide.http import pyfetch
url = "https://ookla-open-data.s3.us-west-2.amazonaws.com/parquet/performance/type=mobile/year=2019/quarter=1/2019-01-01_performance_mobile_tiles.parquet"
local_path = Path("data-filter-extension.parquet")
r = requests.get(url)
table = read_parquet(BytesIO(r.content)).read_all()
table
del r
geometry = ChunkedArray([from_wkt(chunk) for chunk in table["tile"].chunks])
centroids = centroid(geometry)
del geometry
geo_table = table.select(["avg_d_kbps", "avg_u_kbps", "avg_lat_ms"]).append_column("geometry", centroids)
geo_table
del centroids, table
filter_extension = DataFilterExtension(filter_size=3)
avg_d_kbps = geo_table["avg_d_kbps"].to_numpy()
avg_u_kbps = geo_table["avg_u_kbps"].to_numpy()
avg_lat_ms = geo_table["avg_lat_ms"].to_numpy()
min_bound = 5000
max_bound = 50000
normalized_download_speed = (avg_d_kbps - min_bound) / (max_bound - min_bound)
fill_color = apply_continuous_cmap(normalized_download_speed, BrBG_10)
radius = normalized_download_speed * 200
filter_values = np.column_stack(
[avg_d_kbps, avg_u_kbps, avg_lat_ms]
)
initial_filter_range = [
[10_000, 50_000],
[1000, 10_000],
[0, 100],
]
layer = ScatterplotLayer(
table=geo_table,
extensions=[filter_extension],
get_fill_color=fill_color,
get_radius=radius,
get_filter_value=filter_values,
filter_range=initial_filter_range,
radius_units="meters",
radius_min_pixels=0.9,
)
m = Map(layer)
m
page = m