<jupyter_start><jupyter_text>Mapping antenna data to geographic regions Input parameters for this notebook:<jupyter_code>regions_geojson_file = (
    "../data/regions.geojson"  # The GeoJSON file with administrative regions
)
antennas_csv_file = "antenna_pos.csv"  # The CSV file with antenna locations
max_antenna_range = 1000  # The maximum range of an antenna in meters. This is used to crop infinite Voronoi cells to a reasonable size.
epsg_regions = 4326  # The EPSG code of the regions file<jupyter_output><empty_output><jupyter_text>The `mobilephonenetworkanalysis` package is a support library shipped by this package. It can be install with `python -m pip install .` from the repository root directory.<jupyter_code>import pyproj
import functools
import geojson
import geopandas
import itertools
import matplotlib.pyplot as plt
import mobilephonenetworkanalysis
import numpy as np
import shapely.geometry as geo
import scipy.spatial as spatial<jupyter_output><empty_output><jupyter_text>Read the regions from GeoJSON as GeoPandas data frame:<jupyter_code>regions_df = geopandas.read_file(regions_geojson_file)
regions_df.crs = epsg_regions<jupyter_output><empty_output><jupyter_text>Here is a visualization of the regions:<jupyter_code>ax = regions_df.plot(figsize=(20, 8))
ax.set_axis_off()<jupyter_output><empty_output><jupyter_text>Read the antenna positions both as `np.array` and also add them to a dataframe:<jupyter_code>antennas = np.genfromtxt(antennas_csv_file, delimiter=",")
projection = pyproj.Transformer.from_crs(
    "EPSG:4326", f"EPSG:{epsg_regions}", always_xy=False
).transform
antennas = np.apply_along_axis(lambda row: projection(*row), 1, antennas)
antenna_df = geopandas.GeoDataFrame(geometry=[geo.Point(a) for a in antennas])
antenna_df.crs = epsg_regions
ax = regions_df.plot(figsize=(20, 8))
ax.set_axis_off()
ax = antenna_df.plot(ax=ax, color="black", markersize=2)<jupyter_output><empty_output><jupyter_text>Calculate a Voronoi tesselation and transform to a dataframe:<jupyter_code>vor = spatial.Voronoi(antennas)
regions, vertices = mobilephonenetworkanalysis.voronoi_finite_polygons_2d(vor)
antenna_df["voronoi"] = [geo.Polygon([vertices[i] for i in reg]) for reg in regions]
antenna_df = antenna_df.set_geometry("voronoi")<jupyter_output><empty_output><jupyter_text>As the Voronoi diagram extends beyond our specified geographic region, we now intersect each Voronoi region with the union of all regions:<jupyter_code>all_regions = functools.reduce(
    lambda a, b: a.union(b), regions_df.geometry, geo.MultiPolygon()
)
antenna_df["cut_voronoi"] = antenna_df.voronoi.intersection(all_regions)
antenna_df = antenna_df.set_geometry("cut_voronoi")<jupyter_output><empty_output><jupyter_text>In the visualization, we drop all antennas that do not contribute within our regions:<jupyter_code>antenna_df_filt = antenna_df[antenna_df.cut_voronoi.area > 0]
ax = antenna_df_filt.plot(figsize=(20, 8))
ax.set_axis_off()
ax = antenna_df_filt["geometry"].copy().plot(ax=ax, markersize=2, color="black")<jupyter_output><empty_output><jupyter_text>Calculate the transformation matrix that describes the relation ship between antennas and barrios:<jupyter_code>admin2tower = np.zeros(shape=(antenna_df.shape[0], regions_df.shape[0]))
tower2admin = np.zeros(shape=(regions_df.shape[0], antenna_df.shape[0]))
for (i, antenna), (j, region) in itertools.product(
    antenna_df.iterrows(), regions_df.iterrows()
):
    if not antenna["voronoi"].intersects(region["geometry"]):
        continue

    inside_area = all_regions.intersection(antenna["voronoi"]).area
    outside_area = (
        antenna["voronoi"]
        .difference(all_regions)
        .intersection(antenna["geometry"].buffer(max_antenna_range))
        .area
    )

    admin2tower[i, j] = antenna["voronoi"].intersection(region["geometry"]).area / (
        inside_area + outside_area
    )
    tower2admin[j, i] = (
        antenna["voronoi"].intersection(region["geometry"]).area
        / region["geometry"].area
    )<jupyter_output><empty_output><jupyter_text>Write out the two resulting matrices:<jupyter_code>np.save("admin2tower.npy", admin2tower)
np.save("tower2admin.npy", tower2admin)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10810810810810811, 'fraction_numerical': 0.009009009009009009, 'mean_word_length': 6.727106227106227, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '550133', 'license': 'MIT', 'n_tokens_mistral': 1502, 'n_tokens_neox': 1421, 'n_words': 305, 'path': 'notebooks/tesselation.ipynb', 'repo_name': 'ssciwr/mobile-phone-network-analysis', 'size': '4218'}