Py.Cafe

maartenbreddels/

lonboard-mobile-network-analysis

Interactive Analysis of Mobile Network Performance

DocsPricing
  • app.py
  • requirements.txt
app.py
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
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
requirements.txt
1
2
3
4
5
6
7
8
9
solara
arro3-core @ https://ds-wheels.s3.amazonaws.com/arro3_core-0.3.0-cp312-cp312-emscripten_3_1_58_wasm32.whl
arro3-compute @ https://ds-wheels.s3.amazonaws.com/arro3_compute-0.3.0-cp312-cp312-emscripten_3_1_58_wasm32.whl
arro3-io @ https://ds-wheels.s3.amazonaws.com/arro3_io-0.3.0-cp312-cp312-emscripten_3_1_58_wasm32.whl
geoarrow-rust-core @ https://ds-wheels.s3.amazonaws.com/geoarrow_rust_core-0.3.0b1-cp38-abi3-emscripten_3_1_58_wasm32.whl
palettable
matplotlib
lonboard==0.10.0b2