Skip to content

Commit

Permalink
TYP: add type hints to functional._dimension
Browse files Browse the repository at this point in the history
  • Loading branch information
martinfleis committed Jan 12, 2024
1 parent 4627ee2 commit 4b26f95
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 30 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/mypy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Tests

on:
push:
branches: [main]
pull_request:
branches:
- "*"
schedule:
- cron: "0 0 * * 1,4"

jobs:
type-checking:
runs-on: ubuntu-latest
defaults:
run:
shell: bash -l {0}

steps:
- uses: actions/checkout@v4

- name: setup micromamba
uses: mamba-org/setup-micromamba@v1
with:
environment-file: ci/envs/312-latest.yaml
create-args: >-
mypy
- name: Install momepy
run: pip install .

- name: Check momepy
run: |
mypy momepy/ --install-types --ignore-missing-imports --non-interactive
73 changes: 43 additions & 30 deletions momepy/functional/_dimension.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import numpy as np
import pandas as pd
import shapely
from geopandas import GeoDataFrame, GeoSeries
from libpysal.graph import Graph
from numpy.typing import NDArray
from pandas import Series

__all__ = [
"volume",
Expand All @@ -11,7 +14,10 @@
]


def volume(area, height):
def volume(
area: NDArray[np.float_] | Series[float],
height: NDArray[np.float_] | Series[float],
) -> NDArray[np.float_] | Series[float]:
"""
Calculates volume of each object in given GeoDataFrame based on its height and area.
Expand All @@ -20,19 +26,24 @@ def volume(area, height):
Parameters
----------
area : array_like
area : NDArray[np.float_] | Series[float]
array of areas
height : array_like
height : NDArray[np.float_] | Series[float]
array of heights
Returns
-------
array_like
NDArray[np.float_] | Series[float]
array of a type depending on the input
"""
return area * height


def floor_area(area, height, floor_height=3):
def floor_area(
area: NDArray[np.float_] | Series[float],
height: NDArray[np.float_] | Series[float],
floor_height: float | NDArray[np.float_] | Series[float] = 3,
) -> NDArray[np.float_] | Series[float]:
"""Calculates floor area of each object based on height and area.
The number of
Expand All @@ -45,42 +56,43 @@ def floor_area(area, height, floor_height=3):
Parameters
----------
area : array_like
area : NDArray[np.float_] | Series[float]
array of areas
height : array_like
height : NDArray[np.float_] | Series[float]
array of heights
floor_height : float | array_like, optional
float denoting the uniform floor height or an array_like reflecting the building
floor_height : float | NDArray[np.float_] | Series[float], optional
float denoting the uniform floor height or an aarray reflecting the building
height by geometry, by default 3
Returns
-------
array_like
NDArray[np.float_] | Series[float]
array of a type depending on the input
"""
return area * (height // floor_height)


def courtyard_area(gdf):
def courtyard_area(gdf: GeoDataFrame | GeoSeries) -> Series[float]:
"""Calculates area of holes within geometry - area of courtyards.
Parameters
----------
gdf : GeoDataFrame
A GeoDataFrame containing objects to analyse.
gdf : GeoDataFrame | GeoSeries
A GeoDataFrame or GeoSeries containing polygons to analyse.
Returns
-------
pandas.Series
Series[float]
"""
return pd.Series(
return Series(
shapely.area(shapely.polygons(shapely.get_exterior_ring(gdf.geometry.array)))
- gdf.area,
index=gdf.index,
name="courtyard_area",
)


def longest_axis_length(gdf):
def longest_axis_length(gdf: GeoDataFrame | GeoSeries) -> Series[float]:
"""Calculates the length of the longest axis of object.
Axis is defined as a
Expand All @@ -92,35 +104,36 @@ def longest_axis_length(gdf):
Parameters
----------
gdf : GeoDataFrame
A GeoDataFrame containing objects to analyse.
gdf : GeoDataFrame | GeoSeries
A GeoDataFrame or GeoSeries containing polygons to analyse.
Returns
-------
pandas.Series
Series[float]
"""
return shapely.minimum_bounding_radius(gdf.geometry) * 2


def perimeter_wall(gdf, graph=None):
def perimeter_wall(
gdf: GeoDataFrame | GeoSeries, graph: Graph | None = None
) -> Series[float]:
"""
Calculate the perimeter wall length the joined structure.
Parameters
----------
gdf : GeoDataFrame
GeoDataFrame containing objects to analyse
graph : libpysal.graph.Graph, optional
Graph encoding Queen contiguity of ``gdf``
gdf : GeoDataFrame | GeoSeries
A GeoDataFrame or GeoSeries containing polygons to analyse.
graph : Graph | None, optional
Graph encoding Queen contiguity of ``gdf``. If ``None`` Queen contiguity is
built on the fly.
Returns
-------
pandas.Series
Series[float]
"""

if graph is None:
from libpysal.graph import Graph

graph = Graph.build_contiguity(gdf)

isolates = graph.isolates
Expand All @@ -129,13 +142,13 @@ def perimeter_wall(gdf, graph=None):
blocks = gdf.drop(isolates)
component_perimeter = (
blocks[[blocks.geometry.name]]
.set_geometry(blocks.buffer(0.01))
.set_geometry(blocks.buffer(0.01)) # type: ignore
.dissolve(by=graph.component_labels.drop(isolates))
.exterior.length
)

# combine components with isolates
results = pd.Series(np.nan, index=gdf.index, name="perimeter_wall")
results = Series(np.nan, index=gdf.index, name="perimeter_wall")
results.loc[isolates] = gdf.geometry[isolates].exterior.length
results.loc[results.index.drop(isolates)] = component_perimeter.loc[
graph.component_labels.loc[results.index.drop(isolates)]
Expand Down

0 comments on commit 4b26f95

Please sign in to comment.