ObjectNat 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ObjectNat might be problematic. Click here for more details.
- {objectnat-0.2.0 → objectnat-0.2.1}/PKG-INFO +8 -3
- {objectnat-0.2.0 → objectnat-0.2.1}/README.md +6 -1
- {objectnat-0.2.0 → objectnat-0.2.1}/pyproject.toml +2 -2
- objectnat-0.2.1/src/objectnat/_version.py +1 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/methods/provision/city_provision.py +49 -15
- objectnat-0.2.0/src/objectnat/_version.py +0 -1
- {objectnat-0.2.0 → objectnat-0.2.1}/LICENSE.txt +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/__init__.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/_api.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/_config.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/methods/__init__.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/methods/balanced_buildings.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/methods/cluster_points_in_polygons.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/methods/coverage_zones.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/methods/isochrones.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/methods/living_buildings_osm.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/methods/provision/__init__.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/methods/provision/provision.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/methods/provision/provision_exceptions.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/methods/visibility_analysis.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/utils/__init__.py +0 -0
- {objectnat-0.2.0 → objectnat-0.2.1}/src/objectnat/utils/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ObjectNat
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: ObjectNat is an open-source library created for geospatial analysis created by IDU team
|
|
5
5
|
License: BSD-3-Clause
|
|
6
6
|
Author: DDonnyy
|
|
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
14
|
Requires-Dist: geopandas (>=0.14.3,<0.15.0)
|
|
15
|
-
Requires-Dist: iduedu (>=0.1.
|
|
15
|
+
Requires-Dist: iduedu (>=0.1.4,<0.2.0)
|
|
16
16
|
Requires-Dist: joblib (>=1.4.2,<2.0.0)
|
|
17
17
|
Requires-Dist: networkit (>=11.0,<12.0)
|
|
18
18
|
Requires-Dist: networkx (>=3.2.1,<4.0.0)
|
|
@@ -30,6 +30,7 @@ Description-Content-Type: text/markdown
|
|
|
30
30
|
[](https://github.com/psf/black)
|
|
31
31
|
[](https://pypi.org/project/objectnat/)
|
|
32
32
|
|
|
33
|
+
- [РИДМИ (Russian)](README_ru.md)
|
|
33
34
|
<p align="center">
|
|
34
35
|
<img src="https://github.com/user-attachments/assets/d3878cce-8eba-4f96-8458-9a798d436120" alt="logo" width="400">
|
|
35
36
|
</p>
|
|
@@ -80,7 +81,11 @@ Description-Content-Type: text/markdown
|
|
|
80
81
|
between types of services within the clusters.
|
|
81
82
|
|
|
82
83
|
<img src="https://github.com/user-attachments/assets/2a9ad722-87d2-4954-9612-5ac3765aa824" alt="service-clusterization" height="250">
|
|
83
|
-
|
|
84
|
+
|
|
85
|
+
8. **[Living buildings from OSM](./examples/download_buildings_from_osm.ipynb)** - This function downloads building geometries from OpenStreetMap (OSM) for a specified territory and assigns attributes to each building. Specifically, it determines whether a building is residential (`is_living` attribute) and estimates the approximate number of inhabitants (`approximate_pop` attribute).
|
|
86
|
+
|
|
87
|
+
<img src="https://github.com/user-attachments/assets/d60dcd85-1a2e-4342-aae4-561aeda18858" alt="Living buildings" height="250">
|
|
88
|
+
|
|
84
89
|
## Installation
|
|
85
90
|
|
|
86
91
|
**ObjectNat** can be installed with ``pip``:
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
[](https://github.com/psf/black)
|
|
4
4
|
[](https://pypi.org/project/objectnat/)
|
|
5
5
|
|
|
6
|
+
- [РИДМИ (Russian)](README_ru.md)
|
|
6
7
|
<p align="center">
|
|
7
8
|
<img src="https://github.com/user-attachments/assets/d3878cce-8eba-4f96-8458-9a798d436120" alt="logo" width="400">
|
|
8
9
|
</p>
|
|
@@ -53,7 +54,11 @@
|
|
|
53
54
|
between types of services within the clusters.
|
|
54
55
|
|
|
55
56
|
<img src="https://github.com/user-attachments/assets/2a9ad722-87d2-4954-9612-5ac3765aa824" alt="service-clusterization" height="250">
|
|
56
|
-
|
|
57
|
+
|
|
58
|
+
8. **[Living buildings from OSM](./examples/download_buildings_from_osm.ipynb)** - This function downloads building geometries from OpenStreetMap (OSM) for a specified territory and assigns attributes to each building. Specifically, it determines whether a building is residential (`is_living` attribute) and estimates the approximate number of inhabitants (`approximate_pop` attribute).
|
|
59
|
+
|
|
60
|
+
<img src="https://github.com/user-attachments/assets/d60dcd85-1a2e-4342-aae4-561aeda18858" alt="Living buildings" height="250">
|
|
61
|
+
|
|
57
62
|
## Installation
|
|
58
63
|
|
|
59
64
|
**ObjectNat** can be installed with ``pip``:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "ObjectNat"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.1"
|
|
4
4
|
description = "ObjectNat is an open-source library created for geospatial analysis created by IDU team"
|
|
5
5
|
license = "BSD-3-Clause"
|
|
6
6
|
authors = ["DDonnyy <63115678+DDonnyy@users.noreply.github.com>"]
|
|
@@ -19,7 +19,7 @@ networkx = "^3.2.1"
|
|
|
19
19
|
networkit = "^11.0"
|
|
20
20
|
pulp = "^2.8.0"
|
|
21
21
|
population-restorator = "^0.2.3"
|
|
22
|
-
iduedu = "^0.1.
|
|
22
|
+
iduedu = "^0.1.4"
|
|
23
23
|
joblib = "^1.4.2"
|
|
24
24
|
scikit-learn = "^1.4.0"
|
|
25
25
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "0.2.1"
|
|
@@ -12,6 +12,8 @@ from .provision_exceptions import CapacityKeyError, DemandKeyError
|
|
|
12
12
|
|
|
13
13
|
logger = config.logger
|
|
14
14
|
|
|
15
|
+
from pandarallel import pandarallel
|
|
16
|
+
|
|
15
17
|
|
|
16
18
|
class CityProvision:
|
|
17
19
|
"""
|
|
@@ -43,10 +45,10 @@ class CityProvision:
|
|
|
43
45
|
):
|
|
44
46
|
self.services = self.ensure_services(services)
|
|
45
47
|
self.demanded_buildings = self.ensure_buildings(demanded_buildings)
|
|
46
|
-
self.adjacency_matrix = adjacency_matrix
|
|
48
|
+
self.adjacency_matrix = self.delete_useless_matrix_rows(adjacency_matrix.copy(), demanded_buildings, services)
|
|
47
49
|
self.threshold = threshold
|
|
48
50
|
self.check_crs(self.demanded_buildings, self.services)
|
|
49
|
-
|
|
51
|
+
pandarallel.initialize(progress_bar=False, verbose=0)
|
|
50
52
|
|
|
51
53
|
@staticmethod
|
|
52
54
|
def ensure_buildings(v: gpd.GeoDataFrame) -> gpd.GeoDataFrame:
|
|
@@ -71,13 +73,20 @@ class CityProvision:
|
|
|
71
73
|
), f"\nThe CRS in the provided geodataframes are different.\nBuildings CRS:{demanded_buildings.crs}\nServices CRS:{services.crs} \n"
|
|
72
74
|
|
|
73
75
|
@staticmethod
|
|
74
|
-
def delete_useless_matrix_rows(adjacency_matrix, demanded_buildings):
|
|
76
|
+
def delete_useless_matrix_rows(adjacency_matrix, demanded_buildings, services):
|
|
75
77
|
adjacency_matrix.index = adjacency_matrix.index.astype(int)
|
|
76
|
-
|
|
78
|
+
|
|
79
|
+
builds_indexes = set(demanded_buildings.index.astype(int).tolist())
|
|
77
80
|
rows = set(adjacency_matrix.index.astype(int).tolist())
|
|
78
|
-
dif = rows ^
|
|
81
|
+
dif = rows ^ builds_indexes
|
|
79
82
|
adjacency_matrix.drop(index=(list(dif)), axis=0, inplace=True)
|
|
80
83
|
|
|
84
|
+
service_indexes = set(services.index.astype(int).tolist())
|
|
85
|
+
columns = set(adjacency_matrix.columns.astype(int).tolist())
|
|
86
|
+
dif = columns ^ service_indexes
|
|
87
|
+
adjacency_matrix.drop(columns=(list(dif)), axis=0, inplace=True)
|
|
88
|
+
return adjacency_matrix
|
|
89
|
+
|
|
81
90
|
def get_provisions(self) -> Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]:
|
|
82
91
|
self._destination_matrix = pd.DataFrame(
|
|
83
92
|
0,
|
|
@@ -90,6 +99,8 @@ class CityProvision:
|
|
|
90
99
|
len(self.services),
|
|
91
100
|
len(self.demanded_buildings),
|
|
92
101
|
)
|
|
102
|
+
self.adjacency_matrix = self.adjacency_matrix.where(self.adjacency_matrix <= self.threshold * 3, np.inf)
|
|
103
|
+
|
|
93
104
|
self._destination_matrix = self._provision_loop_gravity(
|
|
94
105
|
self.demanded_buildings.copy(),
|
|
95
106
|
self.services.copy(),
|
|
@@ -126,13 +137,22 @@ class CityProvision:
|
|
|
126
137
|
distance_matrix: pd.DataFrame,
|
|
127
138
|
selection_range,
|
|
128
139
|
destination_matrix: pd.DataFrame,
|
|
129
|
-
|
|
140
|
+
best_houses=0.9,
|
|
130
141
|
):
|
|
142
|
+
def apply_function_based_on_size(df, func, axis, threshold=500):
|
|
143
|
+
if len(df) > threshold:
|
|
144
|
+
return df.parallel_apply(func, axis=axis)
|
|
145
|
+
else:
|
|
146
|
+
return df.apply(func, axis=axis)
|
|
147
|
+
|
|
131
148
|
def _calculate_flows_y(loc):
|
|
149
|
+
import numpy as np
|
|
150
|
+
import pandas as pd
|
|
151
|
+
|
|
132
152
|
c = services_table.loc[loc.name]["capacity_left"]
|
|
133
153
|
p = 1 / loc / loc
|
|
134
154
|
p = p / p.sum()
|
|
135
|
-
threshold = p.quantile(
|
|
155
|
+
threshold = p.quantile(best_houses)
|
|
136
156
|
p = p[p >= threshold]
|
|
137
157
|
p = p / p.sum()
|
|
138
158
|
if p.sum() == 0:
|
|
@@ -141,9 +161,13 @@ class CityProvision:
|
|
|
141
161
|
r = pd.Series(0, p.index)
|
|
142
162
|
choice = np.unique(rng.choice(p.index, int(c), p=p.values), return_counts=True)
|
|
143
163
|
choice = r.add(pd.Series(choice[1], choice[0]), fill_value=0)
|
|
164
|
+
|
|
144
165
|
return choice
|
|
145
166
|
|
|
146
167
|
def _balance_flows_to_demands(loc):
|
|
168
|
+
import numpy as np
|
|
169
|
+
import pandas as pd
|
|
170
|
+
|
|
147
171
|
d = houses_table.loc[loc.name]["demand_left"]
|
|
148
172
|
loc = loc[loc > 0]
|
|
149
173
|
if loc.sum() > 0:
|
|
@@ -159,13 +183,20 @@ class CityProvision:
|
|
|
159
183
|
return choice
|
|
160
184
|
return loc
|
|
161
185
|
|
|
162
|
-
temp_destination_matrix =
|
|
186
|
+
temp_destination_matrix = apply_function_based_on_size(
|
|
187
|
+
distance_matrix, lambda x: _calculate_flows_y(x[x <= selection_range]), 1
|
|
188
|
+
)
|
|
189
|
+
|
|
163
190
|
temp_destination_matrix = temp_destination_matrix.fillna(0)
|
|
164
|
-
|
|
191
|
+
|
|
192
|
+
temp_destination_matrix = apply_function_based_on_size(temp_destination_matrix, _balance_flows_to_demands, 0)
|
|
193
|
+
|
|
165
194
|
temp_destination_matrix = temp_destination_matrix.fillna(0)
|
|
166
195
|
destination_matrix = destination_matrix.add(temp_destination_matrix, fill_value=0)
|
|
196
|
+
|
|
167
197
|
axis_1 = destination_matrix.sum(axis=1)
|
|
168
198
|
axis_0 = destination_matrix.sum(axis=0)
|
|
199
|
+
|
|
169
200
|
services_table["capacity_left"] = services_table["capacity"].subtract(axis_1, fill_value=0)
|
|
170
201
|
houses_table["demand_left"] = houses_table["demand"].subtract(axis_0, fill_value=0)
|
|
171
202
|
|
|
@@ -174,16 +205,19 @@ class CityProvision:
|
|
|
174
205
|
columns=houses_table[houses_table["demand_left"] == 0].index.values,
|
|
175
206
|
errors="ignore",
|
|
176
207
|
)
|
|
208
|
+
|
|
209
|
+
distance_matrix = distance_matrix.loc[~(distance_matrix == np.inf).all(axis=1)]
|
|
210
|
+
distance_matrix = distance_matrix.loc[:, ~(distance_matrix == np.inf).all(axis=0)]
|
|
211
|
+
|
|
177
212
|
selection_range += selection_range
|
|
178
213
|
|
|
214
|
+
if best_houses > 0.1:
|
|
215
|
+
best_houses -= 0.1
|
|
216
|
+
if best_houses <= 0.1:
|
|
217
|
+
best_houses = 0
|
|
179
218
|
if len(distance_matrix.columns) > 0 and len(distance_matrix.index) > 0:
|
|
180
219
|
return self._provision_loop_gravity(
|
|
181
|
-
houses_table,
|
|
182
|
-
services_table,
|
|
183
|
-
distance_matrix,
|
|
184
|
-
selection_range,
|
|
185
|
-
destination_matrix,
|
|
186
|
-
temp_destination_matrix,
|
|
220
|
+
houses_table, services_table, distance_matrix, selection_range, destination_matrix, best_houses
|
|
187
221
|
)
|
|
188
222
|
return destination_matrix
|
|
189
223
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = "0.2.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|