Source code for blocksnet.method.weighted_connectivity

import geopandas as gpd
from .base_method import BaseMethod
import numpy as np
import pandas as pd

CONNECTIVITY_COLUMN = "weighted_connectivity"

PLOT_KWARGS = {
    "column": CONNECTIVITY_COLUMN,
    "legend": True,
    "cmap": "cool",
}


[docs]class WeightedConnectivity(BaseMethod): """ Provides methods for block connectivity assessment taking into account population and services within urban blocks. Methods ------- plot(gdf, linewidth=0.1, figsize=(10, 10)) Plots connectivity data on a map. calculate() Calculates connectivity for all blocks in the city model. """
[docs] @staticmethod def plot(gdf: gpd.GeoDataFrame, linewidth: float = 0.1, figsize: tuple[int, int] = (10, 10)): """ Plots connectivity data for blocks on a map. Parameters ---------- gdf : geopandas.GeoDataFrame GeoDataFrame containing block geometries and connectivity data. linewidth : float, optional Line width for plotting the geometries, by default 0.1. figsize : tuple of int, optional Size of the figure to plot, by default (10, 10). Returns ------- None """ gdf.plot(linewidth=linewidth, figsize=figsize, **PLOT_KWARGS).set_axis_off()
[docs] def calculate(self) -> gpd.GeoDataFrame: """ Calculates weighted connectivity for all blocks in the city model. Connectivity is determined by the median value of the accessibility matrix row for each block. Returns ------- geopandas.GeoDataFrame GeoDataFrame containing blocks with calculated connectivity. """ blocks_gdf = self.city_model.get_blocks_gdf()[["geometry", "population"]] # Group services by block and count the number of services in each block blocks_gdf["service_count"] = blocks_gdf.apply(lambda s: len(self.city_model[s.name].all_services), axis=1) # services = self.city_model.get_services_gdf() # service_counts = services.groupby("block_id").size() # blocks_gdf["service_count"] = blocks_gdf.index.map(service_counts).fillna(0).astype(int) # Get accessibility matrix and corresponding population and service counts mx = self.city_model.accessibility_matrix populations = blocks_gdf.loc[mx.index, "population"] service_counts = blocks_gdf.loc[mx.index, "service_count"] # Compute accessibility from houses to services house_to_service = np.outer(populations, service_counts) / mx.values house_to_service = np.where(mx.values != 0, house_to_service, 0) # handle zeros # Compute accessibility from services to houses service_to_house = np.outer(service_counts, populations) / mx.values service_to_house = np.where(mx.values != 0, service_to_house, 0) # Calculate the weighted accessibility matrix as the average of both directions weighted_mx = pd.DataFrame((house_to_service + service_to_house) / 2, index=mx.index, columns=mx.columns) blocks_gdf[CONNECTIVITY_COLUMN] = weighted_mx.mean(axis=1) return blocks_gdf[["geometry", CONNECTIVITY_COLUMN]]