ObjectNat 0.2.5__py3-none-any.whl → 0.2.6__py3-none-any.whl
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/_version.py +1 -1
- objectnat/methods/living_buildings_osm.py +2 -4
- objectnat/methods/provision/provision.py +9 -5
- objectnat/methods/provision/provision_model.py +98 -82
- {objectnat-0.2.5.dist-info → objectnat-0.2.6.dist-info}/METADATA +3 -5
- {objectnat-0.2.5.dist-info → objectnat-0.2.6.dist-info}/RECORD +8 -10
- objectnat/utils/__init__.py +0 -1
- objectnat/utils/utils.py +0 -19
- {objectnat-0.2.5.dist-info → objectnat-0.2.6.dist-info}/LICENSE.txt +0 -0
- {objectnat-0.2.5.dist-info → objectnat-0.2.6.dist-info}/WHEEL +0 -0
objectnat/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
VERSION = "0.2.
|
|
1
|
+
VERSION = "0.2.6"
|
|
@@ -7,8 +7,6 @@ from shapely import MultiPolygon, Polygon
|
|
|
7
7
|
|
|
8
8
|
from objectnat import config
|
|
9
9
|
|
|
10
|
-
from ..utils import get_utm_crs_for_4326_gdf
|
|
11
|
-
|
|
12
10
|
logger = config.logger
|
|
13
11
|
|
|
14
12
|
|
|
@@ -75,8 +73,8 @@ def eval_population(source: gpd.GeoDataFrame, population_column: str, area_per_p
|
|
|
75
73
|
if "building:levels" not in source.columns:
|
|
76
74
|
raise RuntimeError("No 'building:levels' column in provided GeoDataFrame")
|
|
77
75
|
df = source.copy()
|
|
78
|
-
|
|
79
|
-
df["area"] = df.to_crs(
|
|
76
|
+
local_crs = source.estimate_utm_crs()
|
|
77
|
+
df["area"] = df.to_crs(local_crs).geometry.area.astype(float)
|
|
80
78
|
df["building:levels_is_real"] = df["building:levels"].apply(lambda x: False if pd.isna(x) else True)
|
|
81
79
|
df["building:levels"] = df["building:levels"].fillna(1)
|
|
82
80
|
df["building:levels"] = pd.to_numeric(df["building:levels"], errors="coerce")
|
|
@@ -4,8 +4,12 @@ import geopandas as gpd
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import pandas as pd
|
|
6
6
|
|
|
7
|
+
from objectnat import config
|
|
8
|
+
|
|
7
9
|
from .provision_model import Provision
|
|
8
10
|
|
|
11
|
+
logger = config.logger
|
|
12
|
+
|
|
9
13
|
|
|
10
14
|
def get_service_provision(
|
|
11
15
|
buildings: gpd.GeoDataFrame,
|
|
@@ -39,7 +43,7 @@ def get_service_provision(
|
|
|
39
43
|
demanded_buildings=buildings,
|
|
40
44
|
adjacency_matrix=adjacency_matrix,
|
|
41
45
|
threshold=threshold,
|
|
42
|
-
).
|
|
46
|
+
).run()
|
|
43
47
|
return provision_buildings, provision_services, provision_links
|
|
44
48
|
|
|
45
49
|
|
|
@@ -69,12 +73,12 @@ def recalculate_links(
|
|
|
69
73
|
services = services.copy()
|
|
70
74
|
links = links.copy()
|
|
71
75
|
|
|
72
|
-
max_dist = links["distance"].max()
|
|
73
|
-
assert new_max_dist <= max_dist, "New distance exceeds max links distance"
|
|
74
|
-
|
|
75
76
|
links_to_recalculate = links[links["distance"] > new_max_dist]
|
|
76
|
-
|
|
77
|
+
if len(links_to_recalculate) == 0:
|
|
78
|
+
logger.warning("To clip distance exceeds max links distance, returning full provision")
|
|
79
|
+
return buildings, services, links
|
|
77
80
|
|
|
81
|
+
links_to_keep = links[links["distance"] <= new_max_dist]
|
|
78
82
|
free_demand = links_to_recalculate.groupby("building_index").agg({"demand": list, "distance": list})
|
|
79
83
|
free_demand["distance"] = free_demand.apply(
|
|
80
84
|
lambda x: sum((x1 * x2) for x1, x2 in zip(x.demand, x.distance)), axis=1
|
|
@@ -33,7 +33,7 @@ class Provision:
|
|
|
33
33
|
column in 'services' or 'demand' column 'demanded_buildings' GeoDataFrame has no valid value.
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
destination_matrix = None
|
|
37
37
|
|
|
38
38
|
def __init__(
|
|
39
39
|
self,
|
|
@@ -42,12 +42,13 @@ class Provision:
|
|
|
42
42
|
adjacency_matrix: pd.DataFrame,
|
|
43
43
|
threshold: int,
|
|
44
44
|
):
|
|
45
|
-
self.services = self.ensure_services(services)
|
|
46
|
-
self.demanded_buildings = self.ensure_buildings(demanded_buildings)
|
|
47
|
-
self.adjacency_matrix = self.delete_useless_matrix_rows_columns(
|
|
45
|
+
self.services = self.ensure_services(services.copy())
|
|
46
|
+
self.demanded_buildings = self.ensure_buildings(demanded_buildings.copy())
|
|
47
|
+
self.adjacency_matrix = self.delete_useless_matrix_rows_columns(
|
|
48
|
+
adjacency_matrix.copy(), demanded_buildings, services
|
|
49
|
+
).copy()
|
|
48
50
|
self.threshold = threshold
|
|
49
51
|
self.check_crs(self.demanded_buildings, self.services)
|
|
50
|
-
print(config.pandarallel_use_file_system)
|
|
51
52
|
pandarallel.initialize(progress_bar=False, verbose=0, use_memory_fs=config.pandarallel_use_file_system)
|
|
52
53
|
|
|
53
54
|
@staticmethod
|
|
@@ -83,63 +84,16 @@ class Provision:
|
|
|
83
84
|
columns = set(adjacency_matrix.columns.astype(int).tolist())
|
|
84
85
|
dif = columns ^ service_indexes
|
|
85
86
|
adjacency_matrix.drop(columns=(list(dif)), axis=0, inplace=True)
|
|
86
|
-
return adjacency_matrix
|
|
87
|
+
return adjacency_matrix.transpose()
|
|
87
88
|
|
|
88
|
-
def
|
|
89
|
-
self._destination_matrix = pd.DataFrame(
|
|
90
|
-
0,
|
|
91
|
-
index=self.adjacency_matrix.columns,
|
|
92
|
-
columns=self.adjacency_matrix.index,
|
|
93
|
-
)
|
|
94
|
-
self.adjacency_matrix = self.adjacency_matrix.transpose()
|
|
95
|
-
logger.debug(
|
|
96
|
-
"Calculating provision from {} services to {} buildings.",
|
|
97
|
-
len(self.services),
|
|
98
|
-
len(self.demanded_buildings),
|
|
99
|
-
)
|
|
100
|
-
self.adjacency_matrix = self.adjacency_matrix.where(self.adjacency_matrix <= self.threshold * 3, np.inf)
|
|
101
|
-
|
|
102
|
-
self._destination_matrix = self._provision_loop_gravity(
|
|
103
|
-
self.demanded_buildings.copy(),
|
|
104
|
-
self.services.copy(),
|
|
105
|
-
self.adjacency_matrix.copy() + 1,
|
|
106
|
-
self.threshold,
|
|
107
|
-
self._destination_matrix.copy(),
|
|
108
|
-
)
|
|
109
|
-
_additional_options(
|
|
110
|
-
self.demanded_buildings,
|
|
111
|
-
self.services,
|
|
112
|
-
self.adjacency_matrix,
|
|
113
|
-
self._destination_matrix,
|
|
114
|
-
self.threshold,
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
return (
|
|
118
|
-
self.demanded_buildings,
|
|
119
|
-
self.services,
|
|
120
|
-
_calc_links(
|
|
121
|
-
self._destination_matrix,
|
|
122
|
-
self.services,
|
|
123
|
-
self.demanded_buildings,
|
|
124
|
-
self.adjacency_matrix,
|
|
125
|
-
),
|
|
126
|
-
)
|
|
89
|
+
def run(self) -> Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]:
|
|
127
90
|
|
|
128
|
-
|
|
129
|
-
self,
|
|
130
|
-
houses_table: gpd.GeoDataFrame,
|
|
131
|
-
services_table: gpd.GeoDataFrame,
|
|
132
|
-
distance_matrix: pd.DataFrame,
|
|
133
|
-
selection_range,
|
|
134
|
-
destination_matrix: pd.DataFrame,
|
|
135
|
-
best_houses=0.9,
|
|
136
|
-
):
|
|
137
|
-
def apply_function_based_on_size(df, func, axis, threshold=500):
|
|
91
|
+
def apply_function_based_on_size(df, func, axis, threshold=100):
|
|
138
92
|
if len(df) > threshold:
|
|
139
93
|
return df.parallel_apply(func, axis=axis)
|
|
140
94
|
return df.apply(func, axis=axis)
|
|
141
95
|
|
|
142
|
-
def
|
|
96
|
+
def calculate_flows_y(loc):
|
|
143
97
|
import numpy as np # pylint: disable=redefined-outer-name,reimported,import-outside-toplevel
|
|
144
98
|
import pandas as pd # pylint: disable=redefined-outer-name,reimported,import-outside-toplevel
|
|
145
99
|
|
|
@@ -158,7 +112,7 @@ class Provision:
|
|
|
158
112
|
|
|
159
113
|
return choice
|
|
160
114
|
|
|
161
|
-
def
|
|
115
|
+
def balance_flows_to_demands(loc):
|
|
162
116
|
import numpy as np # pylint: disable=redefined-outer-name,reimported,import-outside-toplevel
|
|
163
117
|
import pandas as pd # pylint: disable=redefined-outer-name,reimported,import-outside-toplevel
|
|
164
118
|
|
|
@@ -177,43 +131,104 @@ class Provision:
|
|
|
177
131
|
return choice
|
|
178
132
|
return loc
|
|
179
133
|
|
|
180
|
-
|
|
181
|
-
|
|
134
|
+
logger.debug(
|
|
135
|
+
f"Calculating provision from {len(self.services)} services to {len(self.demanded_buildings)} buildings."
|
|
182
136
|
)
|
|
183
137
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
axis_0 = destination_matrix.sum(axis=0)
|
|
193
|
-
|
|
194
|
-
services_table["capacity_left"] = services_table["capacity"].subtract(axis_1, fill_value=0)
|
|
195
|
-
houses_table["demand_left"] = houses_table["demand"].subtract(axis_0, fill_value=0)
|
|
138
|
+
distance_matrix = self.adjacency_matrix
|
|
139
|
+
destination_matrix = pd.DataFrame(
|
|
140
|
+
0,
|
|
141
|
+
index=distance_matrix.index,
|
|
142
|
+
columns=distance_matrix.columns,
|
|
143
|
+
dtype=int,
|
|
144
|
+
)
|
|
145
|
+
distance_matrix = distance_matrix.where(distance_matrix <= self.threshold * 3, np.inf)
|
|
196
146
|
|
|
147
|
+
houses_table = self.demanded_buildings[["demand", "demand_left"]].copy()
|
|
148
|
+
services_table = self.services[["capacity", "capacity_left"]].copy()
|
|
197
149
|
distance_matrix = distance_matrix.drop(
|
|
198
150
|
index=services_table[services_table["capacity_left"] == 0].index.values,
|
|
199
151
|
columns=houses_table[houses_table["demand_left"] == 0].index.values,
|
|
200
152
|
errors="ignore",
|
|
201
153
|
)
|
|
202
|
-
|
|
203
154
|
distance_matrix = distance_matrix.loc[~(distance_matrix == np.inf).all(axis=1)]
|
|
204
155
|
distance_matrix = distance_matrix.loc[:, ~(distance_matrix == np.inf).all(axis=0)]
|
|
205
156
|
|
|
206
|
-
|
|
157
|
+
distance_matrix = distance_matrix + 1
|
|
158
|
+
selection_range = (self.threshold + 1) / 2
|
|
159
|
+
best_houses = 0.9
|
|
160
|
+
while len(distance_matrix.columns) > 0 and len(distance_matrix.index) > 0:
|
|
161
|
+
objects_n = sum(distance_matrix.shape)
|
|
162
|
+
logger.debug(
|
|
163
|
+
f"Matrix shape: {distance_matrix.shape},"
|
|
164
|
+
f" Total objects: {objects_n},"
|
|
165
|
+
f" Selection range: {selection_range},"
|
|
166
|
+
f" Best houses: {best_houses}"
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
temp_destination_matrix = apply_function_based_on_size(
|
|
170
|
+
distance_matrix, lambda x: calculate_flows_y(x[x <= selection_range]), 1
|
|
171
|
+
)
|
|
207
172
|
|
|
208
|
-
|
|
209
|
-
|
|
173
|
+
temp_destination_matrix = temp_destination_matrix.fillna(0)
|
|
174
|
+
temp_destination_matrix = apply_function_based_on_size(temp_destination_matrix, balance_flows_to_demands, 0)
|
|
175
|
+
temp_destination_matrix = temp_destination_matrix.fillna(0)
|
|
176
|
+
temp_destination_matrix_aligned = temp_destination_matrix.reindex(
|
|
177
|
+
index=destination_matrix.index, columns=destination_matrix.columns, fill_value=0
|
|
178
|
+
)
|
|
179
|
+
del temp_destination_matrix
|
|
180
|
+
destination_matrix_np = destination_matrix.to_numpy()
|
|
181
|
+
temp_destination_matrix_np = temp_destination_matrix_aligned.to_numpy()
|
|
182
|
+
del temp_destination_matrix_aligned
|
|
183
|
+
destination_matrix = pd.DataFrame(
|
|
184
|
+
destination_matrix_np + temp_destination_matrix_np,
|
|
185
|
+
index=destination_matrix.index,
|
|
186
|
+
columns=destination_matrix.columns,
|
|
187
|
+
)
|
|
188
|
+
del destination_matrix_np, temp_destination_matrix_np
|
|
189
|
+
axis_1 = destination_matrix.sum(axis=1).astype(int)
|
|
190
|
+
axis_0 = destination_matrix.sum(axis=0).astype(int)
|
|
191
|
+
|
|
192
|
+
services_table["capacity_left"] = services_table["capacity"].subtract(axis_1, fill_value=0)
|
|
193
|
+
houses_table["demand_left"] = houses_table["demand"].subtract(axis_0, fill_value=0)
|
|
194
|
+
del axis_1, axis_0
|
|
195
|
+
distance_matrix = distance_matrix.drop(
|
|
196
|
+
index=services_table[services_table["capacity_left"] == 0].index.values,
|
|
197
|
+
columns=houses_table[houses_table["demand_left"] == 0].index.values,
|
|
198
|
+
errors="ignore",
|
|
199
|
+
)
|
|
200
|
+
distance_matrix = distance_matrix.loc[~(distance_matrix == np.inf).all(axis=1)]
|
|
201
|
+
distance_matrix = distance_matrix.loc[:, ~(distance_matrix == np.inf).all(axis=0)]
|
|
202
|
+
|
|
203
|
+
selection_range *= 1.5
|
|
210
204
|
if best_houses <= 0.1:
|
|
211
205
|
best_houses = 0
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
206
|
+
else:
|
|
207
|
+
objects_n_new = sum(distance_matrix.shape)
|
|
208
|
+
best_houses = objects_n_new / (objects_n / best_houses)
|
|
209
|
+
|
|
210
|
+
logger.debug("Done!")
|
|
211
|
+
del distance_matrix, houses_table, services_table
|
|
212
|
+
self.destination_matrix = destination_matrix
|
|
213
|
+
|
|
214
|
+
_additional_options(
|
|
215
|
+
self.demanded_buildings,
|
|
216
|
+
self.services,
|
|
217
|
+
self.adjacency_matrix,
|
|
218
|
+
self.destination_matrix,
|
|
219
|
+
self.threshold,
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
return (
|
|
223
|
+
self.demanded_buildings,
|
|
224
|
+
self.services,
|
|
225
|
+
_calc_links(
|
|
226
|
+
self.destination_matrix,
|
|
227
|
+
self.services,
|
|
228
|
+
self.demanded_buildings,
|
|
229
|
+
self.adjacency_matrix,
|
|
230
|
+
),
|
|
231
|
+
)
|
|
217
232
|
|
|
218
233
|
|
|
219
234
|
def _calc_links(
|
|
@@ -279,8 +294,7 @@ def _additional_options(
|
|
|
279
294
|
buildings["supplyed_demands_without"] = 0
|
|
280
295
|
services["carried_capacity_within"] = 0
|
|
281
296
|
services["carried_capacity_without"] = 0
|
|
282
|
-
for i in
|
|
283
|
-
loc = destination_matrix.iloc[i]
|
|
297
|
+
for i, loc in destination_matrix.iterrows():
|
|
284
298
|
distances_all = matrix.loc[loc.name]
|
|
285
299
|
distances = distances_all[distances_all <= normative_distance]
|
|
286
300
|
s = matrix.loc[loc.name] <= normative_distance
|
|
@@ -306,6 +320,7 @@ def _additional_options(
|
|
|
306
320
|
services.at[loc.name, "carried_capacity_without"] = (
|
|
307
321
|
services.at[loc.name, "carried_capacity_without"] + without.sum()
|
|
308
322
|
)
|
|
323
|
+
buildings["min_dist"] = matrix.min(axis=0).replace(np.inf, None)
|
|
309
324
|
buildings["avg_dist"] = (buildings["avg_dist"] / (buildings["demand"] - buildings["demand_left"])).astype(
|
|
310
325
|
np.float32
|
|
311
326
|
)
|
|
@@ -318,3 +333,4 @@ def _additional_options(
|
|
|
318
333
|
buildings["supplyed_demands_without"] = buildings["supplyed_demands_without"].astype(np.uint16)
|
|
319
334
|
services["carried_capacity_within"] = services["carried_capacity_within"].astype(np.uint16)
|
|
320
335
|
services["carried_capacity_without"] = services["carried_capacity_without"].astype(np.uint16)
|
|
336
|
+
logger.debug("Done adding additional options")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ObjectNat
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.6
|
|
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,14 +12,12 @@ 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.2.
|
|
16
|
-
Requires-Dist: joblib (>=1.4.2,<2.0.0)
|
|
15
|
+
Requires-Dist: iduedu (>=0.2.2,<0.3.0)
|
|
17
16
|
Requires-Dist: networkx (>=3.3,<4.0)
|
|
18
|
-
Requires-Dist: numpy (>=1.
|
|
17
|
+
Requires-Dist: numpy (>=1.26.4,<2.0.0)
|
|
19
18
|
Requires-Dist: pandarallel (>=1.6.5,<2.0.0)
|
|
20
19
|
Requires-Dist: pandas (>=2.2.0,<3.0.0)
|
|
21
20
|
Requires-Dist: population-restorator (>=0.2.3,<0.3.0)
|
|
22
|
-
Requires-Dist: pulp (>=2.8.0,<3.0.0)
|
|
23
21
|
Requires-Dist: scikit-learn (>=1.4.0,<2.0.0)
|
|
24
22
|
Requires-Dist: tqdm (>=4.66.2,<5.0.0)
|
|
25
23
|
Description-Content-Type: text/markdown
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
objectnat/__init__.py,sha256=OnDvrLPLEeYIE_9qOVYgMc-PkRzIqShtGxirguEXiRU,260
|
|
2
2
|
objectnat/_api.py,sha256=oiEO2P-tv6AMDdNoT8d0BWMmgeUJa4bhzGDTU2BWTXI,704
|
|
3
3
|
objectnat/_config.py,sha256=sv13J3yMw1cmmkgPMf08zinLwPKYwXHJGfchqmurSg8,2268
|
|
4
|
-
objectnat/_version.py,sha256=
|
|
4
|
+
objectnat/_version.py,sha256=XC2MYZybet-wsd8zs6MBULy8nzAc7dUW0vmpI8ttNTI,18
|
|
5
5
|
objectnat/methods/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
objectnat/methods/balanced_buildings.py,sha256=hLT2QgmGWpROtnL8SJQIujeP6q9ou15yIdHpv66CfMs,2892
|
|
7
7
|
objectnat/methods/cluster_points_in_polygons.py,sha256=ANoPHB89Ih6SYUTs0VoYqW7zi9GVIytSOGySoQ3vby4,5073
|
|
8
8
|
objectnat/methods/coverage_zones.py,sha256=yMeK1DjneMAxxKv9busEKdAsP25xiJMcPCixlJCDI4s,2835
|
|
9
9
|
objectnat/methods/isochrones.py,sha256=CBJprxcyPIYC4RJizqJ1MJL-Zkea4iyr7wHTOOQ7DC8,6146
|
|
10
|
-
objectnat/methods/living_buildings_osm.py,sha256=
|
|
10
|
+
objectnat/methods/living_buildings_osm.py,sha256=Qdh9vq3Da7-aYayZ33eBdo012jleNmQ2evbbrGtdUj8,5820
|
|
11
11
|
objectnat/methods/provision/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
objectnat/methods/provision/provision.py,sha256=
|
|
12
|
+
objectnat/methods/provision/provision.py,sha256=qPPE5G8kylCfWE5SUz8LlxqEsC4NFmIniKVKPeqyRGs,4713
|
|
13
13
|
objectnat/methods/provision/provision_exceptions.py,sha256=-TK4A-vacUuzlPJGSt2YyawRwKDLCZFlAbuIvIf1FnY,1723
|
|
14
|
-
objectnat/methods/provision/provision_model.py,sha256=
|
|
14
|
+
objectnat/methods/provision/provision_model.py,sha256=UqF_4oTzclwaLhU5JvH2Pxqq-pm5GHxXorHAnA0Lpyo,14459
|
|
15
15
|
objectnat/methods/visibility_analysis.py,sha256=__S01m4YcIZbUcr6Umzvr4NpaCsajXxKNcfJm3zquVY,20690
|
|
16
|
-
objectnat/
|
|
17
|
-
objectnat/
|
|
18
|
-
objectnat-0.2.
|
|
19
|
-
objectnat-0.2.
|
|
20
|
-
objectnat-0.2.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
21
|
-
objectnat-0.2.5.dist-info/RECORD,,
|
|
16
|
+
objectnat-0.2.6.dist-info/LICENSE.txt,sha256=yPEioMfTd7JAQgAU6J13inS1BSjwd82HFlRSoIb4My8,1498
|
|
17
|
+
objectnat-0.2.6.dist-info/METADATA,sha256=aB9-0qbiYOC0G-nPS0Vao_IWKuR81lvySTIkeLZcsUQ,5761
|
|
18
|
+
objectnat-0.2.6.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
19
|
+
objectnat-0.2.6.dist-info/RECORD,,
|
objectnat/utils/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .utils import get_utm_crs_for_4326_gdf
|
objectnat/utils/utils.py
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import geopandas as gpd
|
|
2
|
-
from pyproj import CRS
|
|
3
|
-
from pyproj.aoi import AreaOfInterest
|
|
4
|
-
from pyproj.database import query_utm_crs_info
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def get_utm_crs_for_4326_gdf(gdf: gpd.GeoDataFrame) -> CRS:
|
|
8
|
-
assert gdf.crs == CRS.from_epsg(4326), "provided GeoDataFrame is not in EPSG 4326"
|
|
9
|
-
minx, miny, maxx, maxy = gdf.total_bounds
|
|
10
|
-
utm_crs_list = query_utm_crs_info(
|
|
11
|
-
datum_name="WGS 84",
|
|
12
|
-
area_of_interest=AreaOfInterest(
|
|
13
|
-
west_lon_degree=minx,
|
|
14
|
-
south_lat_degree=miny,
|
|
15
|
-
east_lon_degree=maxx,
|
|
16
|
-
north_lat_degree=maxy,
|
|
17
|
-
),
|
|
18
|
-
)
|
|
19
|
-
return CRS.from_epsg(utm_crs_list[0].code)
|
|
File without changes
|
|
File without changes
|