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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
|
import geopandas as gpd
import numpy as np
import pandas as pd
import pytest
from shapely.geometry import LineString, Point, Polygon
import momepy as mm
from momepy import sw_high
from momepy.shape import _make_circle
class TestDimensions:
def setup_method(self):
test_file_path = mm.datasets.get_path("bubenec")
self.df_buildings = gpd.read_file(test_file_path, layer="buildings")
self.df_streets = gpd.read_file(test_file_path, layer="streets")
self.df_tessellation = gpd.read_file(test_file_path, layer="tessellation")
self.df_buildings["height"] = np.linspace(10.0, 30.0, 144)
def test_Area(self):
self.df_buildings["area"] = mm.Area(self.df_buildings).series
check = self.df_buildings.geometry[0].area
assert self.df_buildings["area"][0] == check
def test_Perimeter(self):
self.df_buildings["perimeter"] = mm.Perimeter(self.df_buildings).series
check = self.df_buildings.geometry[0].length
assert self.df_buildings["perimeter"][0] == check
def test_Volume(self):
self.df_buildings["area"] = self.df_buildings.geometry.area
self.df_buildings["volume"] = mm.Volume(
self.df_buildings, "height", "area"
).series
check = self.df_buildings.geometry[0].area * self.df_buildings.height[0]
assert self.df_buildings["volume"][0] == check
area = self.df_buildings.geometry.area
height = np.linspace(10.0, 30.0, 144)
self.df_buildings["volume"] = mm.Volume(self.df_buildings, height, area).series
check = self.df_buildings.geometry[0].area * self.df_buildings.height[0]
assert self.df_buildings["volume"][0] == check
self.df_buildings["volume"] = mm.Volume(self.df_buildings, "height").series
check = self.df_buildings.geometry[0].area * self.df_buildings.height[0]
assert self.df_buildings["volume"][0] == check
with pytest.raises(KeyError, match="nonexistent"):
self.df_buildings["volume"] = mm.Volume(
self.df_buildings, "height", "nonexistent"
)
def test_FloorArea(self):
self.df_buildings["area"] = self.df_buildings.geometry.area
self.df_buildings["floor_area"] = mm.FloorArea(
self.df_buildings, "height", "area"
).series
check = self.df_buildings.geometry[0].area * (self.df_buildings.height[0] // 3)
assert self.df_buildings["floor_area"][0] == check
area = self.df_buildings.geometry.area
height = np.linspace(10.0, 30.0, 144)
self.df_buildings["floor_area"] = mm.FloorArea(
self.df_buildings, height, area
).series
assert self.df_buildings["floor_area"][0] == check
self.df_buildings["floor_area"] = mm.FloorArea(
self.df_buildings, "height"
).series
assert self.df_buildings["floor_area"][0] == check
with pytest.raises(KeyError, match="nonexistent"):
self.df_buildings["floor_area"] = mm.FloorArea(
self.df_buildings, "height", "nonexistent"
)
def test_CourtyardArea(self):
self.df_buildings["area"] = self.df_buildings.geometry.area
self.df_buildings["courtyard_area"] = mm.CourtyardArea(
self.df_buildings, "area"
).series
check = (
Polygon(self.df_buildings.geometry[80].exterior).area
- self.df_buildings.geometry[80].area
)
assert self.df_buildings["courtyard_area"][80] == check
area = self.df_buildings.geometry.area
self.df_buildings["courtyard_area"] = mm.CourtyardArea(
self.df_buildings, area
).series
assert self.df_buildings["courtyard_area"][80] == check
self.df_buildings["courtyard_area"] = mm.CourtyardArea(self.df_buildings).series
assert self.df_buildings["courtyard_area"][80] == check
with pytest.raises(KeyError, match="nonexistent"):
self.df_buildings["courtyard_area"] = mm.CourtyardArea(
self.df_buildings, "nonexistent"
)
def test_LongestAxisLength(self):
self.df_buildings["long_axis"] = mm.LongestAxisLength(self.df_buildings).series
check = (
_make_circle(self.df_buildings.geometry[0].convex_hull.exterior.coords)[2]
* 2
)
assert self.df_buildings["long_axis"][0] == check
def test_AverageCharacter(self):
spatial_weights = sw_high(k=3, gdf=self.df_tessellation, ids="uID")
self.df_tessellation["area"] = area = self.df_tessellation.geometry.area
self.df_tessellation["mesh_ar"] = mm.AverageCharacter(
self.df_tessellation,
values="area",
spatial_weights=spatial_weights,
unique_id="uID",
mode="mode",
).mode
self.df_tessellation["mesh_array"] = mm.AverageCharacter(
self.df_tessellation,
values=area,
spatial_weights=spatial_weights,
unique_id="uID",
mode="median",
).median
self.df_tessellation["mesh_id"] = mm.AverageCharacter(
self.df_tessellation,
spatial_weights=spatial_weights,
values="area",
rng=(10, 90),
unique_id="uID",
).mean
self.df_tessellation["mesh_iq"] = mm.AverageCharacter(
self.df_tessellation,
spatial_weights=spatial_weights,
values="area",
rng=(25, 75),
unique_id="uID",
).series
all_m = mm.AverageCharacter(
self.df_tessellation,
spatial_weights=spatial_weights,
values="area",
unique_id="uID",
)
two = mm.AverageCharacter(
self.df_tessellation,
spatial_weights=spatial_weights,
values="area",
unique_id="uID",
mode=["mean", "median"],
)
with pytest.raises(ValueError, match="nonexistent is not supported as mode."):
self.df_tessellation["mesh_ar"] = mm.AverageCharacter(
self.df_tessellation,
values="area",
spatial_weights=spatial_weights,
unique_id="uID",
mode="nonexistent",
)
with pytest.raises(ValueError, match="nonexistent is not supported as mode."):
self.df_tessellation["mesh_ar"] = mm.AverageCharacter(
self.df_tessellation,
values="area",
spatial_weights=spatial_weights,
unique_id="uID",
mode=["nonexistent", "mean"],
)
assert self.df_tessellation["mesh_ar"][0] == pytest.approx(249.503, rel=1e-3)
assert self.df_tessellation["mesh_array"][0] == pytest.approx(
2623.996, rel=1e-3
)
assert self.df_tessellation["mesh_id"][38] == pytest.approx(2250.224, rel=1e-3)
assert self.df_tessellation["mesh_iq"][38] == pytest.approx(2118.609, rel=1e-3)
assert all_m.mean[0] == pytest.approx(2922.957, rel=1e-3)
assert all_m.median[0] == pytest.approx(2623.996, rel=1e-3)
assert all_m.mode[0] == pytest.approx(249.503, rel=1e-3)
assert all_m.series[0] == pytest.approx(2922.957, rel=1e-3)
assert two.mean[0] == pytest.approx(2922.957, rel=1e-3)
assert two.median[0] == pytest.approx(2623.996, rel=1e-3)
sw_drop = sw_high(k=3, gdf=self.df_tessellation[2:], ids="uID")
assert (
mm.AverageCharacter(
self.df_tessellation,
values="area",
spatial_weights=sw_drop,
unique_id="uID",
)
.series.isna()
.any()
)
def test_StreetProfile(self):
results = mm.StreetProfile(self.df_streets, self.df_buildings, heights="height")
assert results.w[0] == 47.9039130128257
assert results.wd[0] == 0.026104885468705645
assert results.h[0] == 15.26806526806527
assert results.p[0] == 0.31872271611668607
assert results.o[0] == 0.9423076923076923
assert results.hd[0] == 9.124556701878003
height = np.linspace(10.0, 30.0, 144)
results2 = mm.StreetProfile(
self.df_streets, self.df_buildings, heights=height, tick_length=100
)
assert results2.w[0] == 70.7214870365335
assert results2.wd[0] == pytest.approx(8.50508193935929)
assert results2.h[0] == pytest.approx(23.87158296249206)
assert results2.p[0] == pytest.approx(0.3375435664999579)
assert results2.o[0] == 0.5769230769230769
assert results2.hd[0] == pytest.approx(5.9307227575674)
results3 = mm.StreetProfile(self.df_streets, self.df_buildings)
assert results3.w[0] == 47.9039130128257
assert results3.wd[0] == 0.026104885468705645
assert results3.o[0] == 0.9423076923076923
# avoid infinity
blg = gpd.GeoDataFrame(
{"height": [2, 5]},
geometry=[
Point(0, 0).buffer(10, cap_style=3),
Point(30, 0).buffer(10, cap_style=3),
],
)
lines = gpd.GeoDataFrame(
geometry=[LineString([(-8, -8), (8, 8)]), LineString([(15, -10), (15, 10)])]
)
assert mm.StreetProfile(lines, blg, "height", 2).p.equals(
pd.Series([np.nan, 0.35])
)
def test_WeightedCharacter(self):
sw = sw_high(k=3, gdf=self.df_tessellation, ids="uID")
weighted = mm.WeightedCharacter(self.df_buildings, "height", sw, "uID").series
assert weighted[38] == pytest.approx(18.301, rel=1e-3)
self.df_buildings["area"] = self.df_buildings.geometry.area
sw = sw_high(k=3, gdf=self.df_tessellation, ids="uID")
weighted = mm.WeightedCharacter(
self.df_buildings, "height", sw, "uID", "area"
).series
assert weighted[38] == pytest.approx(18.301, rel=1e-3)
area = self.df_buildings.geometry.area
sw = sw_high(k=3, gdf=self.df_tessellation, ids="uID")
weighted = mm.WeightedCharacter(
self.df_buildings, self.df_buildings.height, sw, "uID", area
).series
assert weighted[38] == pytest.approx(18.301, rel=1e-3)
sw_drop = sw_high(k=3, gdf=self.df_tessellation[2:], ids="uID")
assert (
mm.WeightedCharacter(self.df_buildings, "height", sw_drop, "uID")
.series.isna()
.any()
)
def test_CoveredArea(self):
sw = sw_high(gdf=self.df_tessellation, k=1, ids="uID")
covered_sw = mm.CoveredArea(self.df_tessellation, sw, "uID").series
assert covered_sw[0] == pytest.approx(24115.667, rel=1e-3)
sw_drop = sw_high(k=3, gdf=self.df_tessellation[2:], ids="uID")
assert mm.CoveredArea(self.df_tessellation, sw_drop, "uID").series.isna().any()
def test_PerimeterWall(self):
sw = sw_high(gdf=self.df_buildings, k=1)
wall = mm.PerimeterWall(self.df_buildings).series
wall_sw = mm.PerimeterWall(self.df_buildings, sw).series
assert wall[0] == wall_sw[0]
assert wall[0] == pytest.approx(137.210, rel=1e-3)
def test_SegmentsLength(self):
absol = mm.SegmentsLength(self.df_streets).sum
mean = mm.SegmentsLength(self.df_streets, mean=True).mean
assert max(absol) == pytest.approx(1907.502238338006)
assert max(mean) == pytest.approx(249.5698434867373)
|