Skip to content

Commit

Permalink
feat: land use prediction docstring and example
Browse files Browse the repository at this point in the history
  • Loading branch information
vasilstar97 committed Jul 31, 2024
1 parent 827580c commit 5ea8ef9
Show file tree
Hide file tree
Showing 7 changed files with 449 additions and 51 deletions.
172 changes: 142 additions & 30 deletions blocksnet/method/land_use_prediction/land_use_prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,84 @@
import geopandas as gpd
import pandas as pd
from tqdm import trange
from sklearn.metrics.pairwise import cosine_similarity

from ...models.land_use import LandUse
from ..base_method import BaseMethod
from sklearn.metrics.pairwise import cosine_similarity

PREDICTION_COLUMN = "land_use"


class LandUsePrediction(BaseMethod):
"""
A class used to predict land use based on various methods including cosine similarity.
Methods
-------
plot(gdf: gpd.GeoDataFrame, linewidth=0.1, figsize=(10, 10)):
Plots the GeoDataFrame with predicted land use.
_get_land_uses_services():
Retrieves land use service types for the city model.
_get_blocks_gdf():
Retrieves block geometries and their service capacities as a GeoDataFrame.
_get_unique_per_landuse(landuse_items):
Finds unique service tags for each land use.
_intersects(set1, set2):
Checks if two sets have any common elements.
_predict_block_landuse_cosine_similarity(block_vector, landuse_vectors, return_prob=False):
Predicts land use for a block using cosine similarity.
_predict_block_landuse(codes_in_block, landuse_items, use_cos_similarity=True):
Predicts the land use for a block.
calculate(use_cos_similarity=True):
Calculates the land use prediction for all blocks.
"""

@staticmethod
def plot(gdf: gpd.GeoDataFrame, figsize=(10, 10)):
ax = gdf.plot(color="#ddd", figsize=figsize)
gdf.plot(ax=ax, column=PREDICTION_COLUMN, legend=True)
def plot(gdf: gpd.GeoDataFrame, linewidth: float = 0.1, figsize: tuple[int, int] = (10, 10)):
"""
Plots the GeoDataFrame with predicted land use.
Parameters
----------
gdf : gpd.GeoDataFrame
GeoDataFrame containing the geometries and predicted land use.
linewidth : float, optional
Size of the polygon border to plot, by default 0.1.
figsize : tuple, optional
Size of the figure to plot, by default (10, 10).
"""
ax = gdf.plot(color="#ddd", linewidth=linewidth, figsize=figsize)
gdf.plot(ax=ax, column=PREDICTION_COLUMN, linewidth=linewidth, legend=True)
ax.set_axis_off()

def _get_land_uses_services(self):
def _get_land_uses_services(self) -> dict[str, list[str]]:
"""
Retrieves land use service types for the city model.
Returns
-------
dict
Dictionary with land use names as keys and lists of service types as values.
"""
get_land_use_services = lambda lu: [st.name for st in self.city_model.get_land_use_service_types(lu)]
return {lu.name: get_land_use_services(lu) for lu in LandUse}

def _get_blocks_gdf(self):
def _get_blocks_gdf(self) -> gpd.GeoDataFrame:
"""
Retrieves block geometries and their service capacities as a GeoDataFrame.
Returns
-------
gpd.GeoDataFrame
GeoDataFrame with block geometries and boolean values representing the presence of each service type.
"""
blocks = self.city_model.get_blocks_gdf()
blocks_profiles = blocks[["geometry"]].copy()
for service_type in self.city_model.service_types:
Expand All @@ -33,10 +92,20 @@ def _get_blocks_gdf(self):
return blocks_profiles

@staticmethod
def _get_unique_per_landuse(landuse_items):
# landuse_items : dict – dictionary containing service codes or service tags for each land use
def _get_unique_per_landuse(landuse_items) -> dict[LandUse, set[str]]:
"""
Finds unique service tags for each land use.
Parameters
----------
landuse_items : dict
Dictionary containing service codes or service tags for each land use.
# returns dict
Returns
-------
dict
Dictionary with land use categories as keys and sets of unique service tags as values.
"""

unique_per_landuse = {}

Expand All @@ -51,12 +120,22 @@ def _get_unique_per_landuse(landuse_items):
return unique_per_landuse

@staticmethod
def _intersects(set1, set2):
# set1 : np.array | list | set
# set2 : np.array | list | set

# returns bool

def _intersects(set1, set2) -> bool:
"""
Checks if two sets have any common elements.
Parameters
----------
set1 : np.array | list | set
First collection of elements.
set2 : np.array | list | set
Second collection of elements.
Returns
-------
bool
True if there are common elements, False otherwise.
"""
if set1 is not set:
set1 = set(set1)
if set2 is not set:
Expand All @@ -65,11 +144,24 @@ def _intersects(set1, set2):
return len(set1.intersection(set2)) > 0

@staticmethod
def _predict_block_landuse_cosine_similarity(block_vector, landuse_vectors, return_prob=False):
# block_vector : list | np.array – collection of booleans representing services present in a block
# landuse_vectors : dict – dictionary containing vectors representing services present in each land use

# returns str or None
def _predict_block_landuse_cosine_similarity(block_vector, landuse_vectors, return_prob=False) -> str | None:
"""
Predicts land use for a block using cosine similarity.
Parameters
----------
block_vector : list | np.array
Collection of booleans representing services present in a block.
landuse_vectors : dict
Dictionary containing vectors representing services present in each land use.
return_prob : bool, optional
If True, also returns the probability of the prediction, by default False.
Returns
-------
str or None
Predicted land use category or None if no prediction is made.
"""

similarity_dict = {}

Expand All @@ -89,11 +181,23 @@ def _predict_block_landuse_cosine_similarity(block_vector, landuse_vectors, retu
return predicted_landuse

def _predict_block_landuse(self, codes_in_block, landuse_items, use_cos_similarity=True):
# codes_in_block : list | np.array – list of service tags or service codes present in a block
# landuse_items : dict – dictionary containing service codes or service tags for each land use
# use_cos_similarity : bool – use cosine similarity to predict unpredicted land uses for blocks

# returns str or None
"""
Predicts the land use for a block.
Parameters
----------
codes_in_block : list | np.array
List of service tags or service codes present in a block.
landuse_items : dict
Dictionary containing service codes or service tags for each land use.
use_cos_similarity : bool, optional
Use cosine similarity to predict unpredicted land uses for blocks, by default True.
Returns
-------
str or None
Predicted land use category or None if no prediction is made.
"""

if len(codes_in_block) == 0:
return None
Expand Down Expand Up @@ -125,11 +229,19 @@ def _predict_block_landuse(self, codes_in_block, landuse_items, use_cos_similari
return

def calculate(self, use_cos_similarity=True):
# block_profile : geopandas.GeoDataFrame – geodataframe with service categories as columns and boolean values representing presence or absence of said service categories in a block
# landuse_items : dict – dictionary containing service codes or service tags for each land use
# use_cos_similarity : bool – use cosine similarity to predict unpredicted land uses for blocks

# returns geopandas.GeoDataFrame
"""
Calculates the land use prediction for all blocks.
Parameters
----------
use_cos_similarity : bool, optional
Use cosine similarity to predict unpredicted land uses for blocks, by default True.
Returns
-------
gpd.GeoDataFrame
GeoDataFrame containing the geometries and predicted land use for all blocks.
"""

blocks_profiles = self._get_blocks_gdf()
landuse_items = self._get_land_uses_services()
Expand Down
2 changes: 1 addition & 1 deletion docs/source/api/method/land_use_prediction.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
LandUsePrediction
============
=================

.. automodule:: blocksnet.method.land_use_prediction.land_use_prediction
4 changes: 4 additions & 0 deletions docs/source/api/utils/helpers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Helpers
=======

.. automodule:: blocksnet.utils.helpers
1 change: 1 addition & 0 deletions docs/source/examples/methods/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ The examples of how to operate the `City` model to perform certain analytics.
diversity
centrality
spacematrix
land_use_prediction
3 changes: 3 additions & 0 deletions docs/source/examples/methods/land_use_prediction.nblink
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"path": "../../../../examples/methods/land_use_prediction.ipynb"
}
Loading

0 comments on commit 5ea8ef9

Please sign in to comment.