ObjectNat 0.1.5__tar.gz → 0.2.0__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.1.5 → objectnat-0.2.0}/PKG-INFO +29 -20
- {objectnat-0.1.5 → objectnat-0.2.0}/README.md +24 -15
- {objectnat-0.1.5 → objectnat-0.2.0}/pyproject.toml +16 -9
- objectnat-0.2.0/src/objectnat/__init__.py +13 -0
- objectnat-0.1.5/src/objectnat/__init__.py → objectnat-0.2.0/src/objectnat/_api.py +3 -7
- objectnat-0.2.0/src/objectnat/_config.py +67 -0
- objectnat-0.2.0/src/objectnat/_version.py +1 -0
- {objectnat-0.1.5 → objectnat-0.2.0}/src/objectnat/methods/balanced_buildings.py +4 -1
- {objectnat-0.1.5 → objectnat-0.2.0}/src/objectnat/methods/cluster_points_in_polygons.py +4 -1
- {objectnat-0.1.5 → objectnat-0.2.0}/src/objectnat/methods/coverage_zones.py +6 -21
- objectnat-0.2.0/src/objectnat/methods/isochrones.py +140 -0
- {objectnat-0.1.5 → objectnat-0.2.0}/src/objectnat/methods/living_buildings_osm.py +24 -94
- objectnat-0.2.0/src/objectnat/methods/provision/__init__.py +0 -0
- objectnat-0.2.0/src/objectnat/methods/provision/city_provision.py +291 -0
- objectnat-0.2.0/src/objectnat/methods/provision/provision.py +90 -0
- objectnat-0.2.0/src/objectnat/methods/provision/provision_exceptions.py +59 -0
- {objectnat-0.1.5 → objectnat-0.2.0}/src/objectnat/methods/visibility_analysis.py +4 -1
- objectnat-0.1.5/src/objectnat/methods/adjacency_matrix.py +0 -39
- objectnat-0.1.5/src/objectnat/methods/demands.py +0 -43
- objectnat-0.1.5/src/objectnat/methods/isochrones.py +0 -66
- objectnat-0.1.5/src/objectnat/methods/osm_graph.py +0 -23
- objectnat-0.1.5/src/objectnat/methods/provision.py +0 -135
- {objectnat-0.1.5 → objectnat-0.2.0}/LICENSE.txt +0 -0
- {objectnat-0.1.5 → objectnat-0.2.0}/src/objectnat/methods/__init__.py +0 -0
- {objectnat-0.1.5 → objectnat-0.2.0}/src/objectnat/utils/__init__.py +0 -0
- {objectnat-0.1.5 → objectnat-0.2.0}/src/objectnat/utils/utils.py +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ObjectNat
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: ObjectNat is an open-source library created for geospatial analysis created by IDU team
|
|
5
5
|
License: BSD-3-Clause
|
|
6
|
-
Author:
|
|
6
|
+
Author: DDonnyy
|
|
7
7
|
Author-email: 63115678+DDonnyy@users.noreply.github.com
|
|
8
|
-
Requires-Python: >=3.10,<
|
|
8
|
+
Requires-Python: >=3.10,<3.13
|
|
9
9
|
Classifier: License :: OSI Approved :: BSD License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
-
Requires-Dist: dongraphio (>=0.3.13,<0.4.0)
|
|
15
14
|
Requires-Dist: geopandas (>=0.14.3,<0.15.0)
|
|
15
|
+
Requires-Dist: iduedu (>=0.1.3,<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)
|
|
@@ -20,7 +20,7 @@ Requires-Dist: numpy (>=1.23.5,<2.0.0)
|
|
|
20
20
|
Requires-Dist: pandarallel (>=1.6.5,<2.0.0)
|
|
21
21
|
Requires-Dist: pandas (>=2.2.0,<3.0.0)
|
|
22
22
|
Requires-Dist: population-restorator (>=0.2.3,<0.3.0)
|
|
23
|
-
Requires-Dist:
|
|
23
|
+
Requires-Dist: pulp (>=2.8.0,<3.0.0)
|
|
24
24
|
Requires-Dist: scikit-learn (>=1.4.0,<2.0.0)
|
|
25
25
|
Requires-Dist: tqdm (>=4.66.2,<5.0.0)
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
@@ -28,58 +28,58 @@ Description-Content-Type: text/markdown
|
|
|
28
28
|
# ObjectNat - Meta Library
|
|
29
29
|
|
|
30
30
|
[](https://github.com/psf/black)
|
|
31
|
+
[](https://pypi.org/project/objectnat/)
|
|
31
32
|
|
|
32
33
|
<p align="center">
|
|
33
|
-
<img src="https://
|
|
34
|
+
<img src="https://github.com/user-attachments/assets/d3878cce-8eba-4f96-8458-9a798d436120" alt="logo" width="400">
|
|
34
35
|
</p>
|
|
35
36
|
|
|
36
37
|
#### **ObjectNat** is an open-source library created for geospatial analysis created by **IDU team**
|
|
37
38
|
|
|
38
39
|
## ObjectNat Components
|
|
39
40
|
|
|
40
|
-
- [
|
|
41
|
-
- [provisio](https://github.com/DDonnyy/provisio) : `provisio` provides main provisio fuctions
|
|
41
|
+
- [IduEdu](https://github.com/DDonnyy/IduEdu) : `IduEdu` provides graph functions
|
|
42
42
|
- [population-restorator](https://github.com/kanootoko/population-restorator) : `restorator` provides city resettlement
|
|
43
43
|
|
|
44
44
|
## Features and how to use
|
|
45
45
|
|
|
46
|
-
1. **[City graph from OSM](
|
|
47
|
-
transport graph from OpenStreetMap (OSM) and creating Intermodal graph.
|
|
46
|
+
1. **[City graph from OSM (IduEdu)](https://github.com/DDonnyy/IduEdu/blob/main/examples/get_any_graph.ipynb)** - Functions to assemble a road, pedestrian,
|
|
47
|
+
and public transport graph from OpenStreetMap (OSM) and creating Intermodal graph.
|
|
48
48
|
|
|
49
|
-
<img src="https://
|
|
49
|
+
<img src="https://github.com/user-attachments/assets/8dc98da9-8462-415e-8cc8-bdfca788e206" alt="IntermodalGraph" height="250">
|
|
50
50
|
|
|
51
51
|
2. **[Adjacency matrix](./examples/calculate_adjacency_matrix.ipynb)** - Calculate adjacency matrix based on the provided
|
|
52
52
|
graph and edge weight type (time or distance). The intermodal graph can be obtained using the previous example.
|
|
53
|
+
|
|
53
54
|
3. **[Isochrones,transport accessibility](./examples/isochrone_generator.ipynb)** - Function for generating isochrones to
|
|
54
55
|
analyze transportation accessibility from specified starting coordinates. Isochrones can be constructed based on
|
|
55
56
|
pedestrian, automobile, or public transport graphs, or a combination thereof.
|
|
56
57
|
|
|
57
|
-
<img src="https://
|
|
58
|
+
<img src="https://github.com/user-attachments/assets/37f308a5-db56-497d-b080-4edef3584fe5" alt="isochrones" height="250">
|
|
58
59
|
|
|
59
60
|
4. **[Population restoration](./examples/restore_population.ipynb)** - Function for resettling population into the provided
|
|
60
61
|
layer of residential buildings. This function distributes people among dwellings based on the total city population
|
|
61
62
|
and the living area of each house.
|
|
62
63
|
5. **[Service provision](./examples/calculate_provision.ipynb)** - Function for calculating the provision of residential
|
|
63
|
-
buildings and population with services.
|
|
64
|
-
|
|
64
|
+
buildings and population with services.
|
|
65
|
+
|
|
66
|
+
<img src="https://github.com/user-attachments/assets/5f2b3c55-9a02-4d70-80f4-503b77023eda" alt="ProvisionSchools" height="250">
|
|
65
67
|
|
|
66
|
-
<img src="https://i.ibb.co/CW7Xj5F/Burger-Provision5min.webp" alt="Burger-Provision5min" height="250">
|
|
67
|
-
|
|
68
68
|
6. **[Visibility analysis](./examples/visibility_analysis.ipynb)** - Function to get a quick estimate of visibility from a
|
|
69
69
|
given point(s) to buildings within a given distance. Also, there is a visibility catchment area calculator for a
|
|
70
70
|
large
|
|
71
71
|
urban area. This function is designed to work with at least 1000 points spaced 10-20 meters apart for optimal
|
|
72
72
|
results. Points can be generated using a road graph and random point distribution along edges.
|
|
73
73
|
|
|
74
|
-
<img src="https://
|
|
75
|
-
|
|
76
|
-
<img src="https://i.ibb.co/zNRzXc5/visibility-catchment-area.webp" alt="visibility-catchment-area" height="250">
|
|
74
|
+
<img src="https://github.com/user-attachments/assets/2927ac86-01e8-4b0e-9ea8-72ad81c13cf5" alt="visibility-from-point" height="250">
|
|
77
75
|
|
|
76
|
+
<img src="https://github.com/user-attachments/assets/b5b0d4b3-a02f-4ade-8772-475703cd6435" alt="visibility-catchment-area" height="250">
|
|
77
|
+
|
|
78
78
|
7. **[Point clusterization](./examples/point_clusterization.ipynb)** - Function to generate cluster polygons for given
|
|
79
79
|
points based on a specified minimum distance and minimum points per cluster. Optionally, calculate the relative ratio
|
|
80
80
|
between types of services within the clusters.
|
|
81
81
|
|
|
82
|
-
<img src="https://
|
|
82
|
+
<img src="https://github.com/user-attachments/assets/2a9ad722-87d2-4954-9612-5ac3765aa824" alt="service-clusterization" height="250">
|
|
83
83
|
|
|
84
84
|
## Installation
|
|
85
85
|
|
|
@@ -88,7 +88,16 @@ Description-Content-Type: text/markdown
|
|
|
88
88
|
```
|
|
89
89
|
pip install ObjectNat
|
|
90
90
|
```
|
|
91
|
+
### Configuration changes
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from objectnat import config
|
|
91
95
|
|
|
96
|
+
config.set_timeout(10) # Timeout for overpass queries
|
|
97
|
+
config.change_logger_lvl('INFO') # To mute all debug msgs
|
|
98
|
+
config.set_enable_tqdm(False) # To mute all tqdm's progress bars
|
|
99
|
+
config.set_overpass_url('http://your.overpass-api.de/interpreter/URL')
|
|
100
|
+
```
|
|
92
101
|
## Contacts
|
|
93
102
|
|
|
94
103
|
- [NCCR](https://actcognitive.org/) - National
|
|
@@ -1,58 +1,58 @@
|
|
|
1
1
|
# ObjectNat - Meta Library
|
|
2
2
|
|
|
3
3
|
[](https://github.com/psf/black)
|
|
4
|
+
[](https://pypi.org/project/objectnat/)
|
|
4
5
|
|
|
5
6
|
<p align="center">
|
|
6
|
-
<img src="https://
|
|
7
|
+
<img src="https://github.com/user-attachments/assets/d3878cce-8eba-4f96-8458-9a798d436120" alt="logo" width="400">
|
|
7
8
|
</p>
|
|
8
9
|
|
|
9
10
|
#### **ObjectNat** is an open-source library created for geospatial analysis created by **IDU team**
|
|
10
11
|
|
|
11
12
|
## ObjectNat Components
|
|
12
13
|
|
|
13
|
-
- [
|
|
14
|
-
- [provisio](https://github.com/DDonnyy/provisio) : `provisio` provides main provisio fuctions
|
|
14
|
+
- [IduEdu](https://github.com/DDonnyy/IduEdu) : `IduEdu` provides graph functions
|
|
15
15
|
- [population-restorator](https://github.com/kanootoko/population-restorator) : `restorator` provides city resettlement
|
|
16
16
|
|
|
17
17
|
## Features and how to use
|
|
18
18
|
|
|
19
|
-
1. **[City graph from OSM](
|
|
20
|
-
transport graph from OpenStreetMap (OSM) and creating Intermodal graph.
|
|
19
|
+
1. **[City graph from OSM (IduEdu)](https://github.com/DDonnyy/IduEdu/blob/main/examples/get_any_graph.ipynb)** - Functions to assemble a road, pedestrian,
|
|
20
|
+
and public transport graph from OpenStreetMap (OSM) and creating Intermodal graph.
|
|
21
21
|
|
|
22
|
-
<img src="https://
|
|
22
|
+
<img src="https://github.com/user-attachments/assets/8dc98da9-8462-415e-8cc8-bdfca788e206" alt="IntermodalGraph" height="250">
|
|
23
23
|
|
|
24
24
|
2. **[Adjacency matrix](./examples/calculate_adjacency_matrix.ipynb)** - Calculate adjacency matrix based on the provided
|
|
25
25
|
graph and edge weight type (time or distance). The intermodal graph can be obtained using the previous example.
|
|
26
|
+
|
|
26
27
|
3. **[Isochrones,transport accessibility](./examples/isochrone_generator.ipynb)** - Function for generating isochrones to
|
|
27
28
|
analyze transportation accessibility from specified starting coordinates. Isochrones can be constructed based on
|
|
28
29
|
pedestrian, automobile, or public transport graphs, or a combination thereof.
|
|
29
30
|
|
|
30
|
-
<img src="https://
|
|
31
|
+
<img src="https://github.com/user-attachments/assets/37f308a5-db56-497d-b080-4edef3584fe5" alt="isochrones" height="250">
|
|
31
32
|
|
|
32
33
|
4. **[Population restoration](./examples/restore_population.ipynb)** - Function for resettling population into the provided
|
|
33
34
|
layer of residential buildings. This function distributes people among dwellings based on the total city population
|
|
34
35
|
and the living area of each house.
|
|
35
36
|
5. **[Service provision](./examples/calculate_provision.ipynb)** - Function for calculating the provision of residential
|
|
36
|
-
buildings and population with services.
|
|
37
|
-
|
|
37
|
+
buildings and population with services.
|
|
38
|
+
|
|
39
|
+
<img src="https://github.com/user-attachments/assets/5f2b3c55-9a02-4d70-80f4-503b77023eda" alt="ProvisionSchools" height="250">
|
|
38
40
|
|
|
39
|
-
<img src="https://i.ibb.co/CW7Xj5F/Burger-Provision5min.webp" alt="Burger-Provision5min" height="250">
|
|
40
|
-
|
|
41
41
|
6. **[Visibility analysis](./examples/visibility_analysis.ipynb)** - Function to get a quick estimate of visibility from a
|
|
42
42
|
given point(s) to buildings within a given distance. Also, there is a visibility catchment area calculator for a
|
|
43
43
|
large
|
|
44
44
|
urban area. This function is designed to work with at least 1000 points spaced 10-20 meters apart for optimal
|
|
45
45
|
results. Points can be generated using a road graph and random point distribution along edges.
|
|
46
46
|
|
|
47
|
-
<img src="https://
|
|
48
|
-
|
|
49
|
-
<img src="https://i.ibb.co/zNRzXc5/visibility-catchment-area.webp" alt="visibility-catchment-area" height="250">
|
|
47
|
+
<img src="https://github.com/user-attachments/assets/2927ac86-01e8-4b0e-9ea8-72ad81c13cf5" alt="visibility-from-point" height="250">
|
|
50
48
|
|
|
49
|
+
<img src="https://github.com/user-attachments/assets/b5b0d4b3-a02f-4ade-8772-475703cd6435" alt="visibility-catchment-area" height="250">
|
|
50
|
+
|
|
51
51
|
7. **[Point clusterization](./examples/point_clusterization.ipynb)** - Function to generate cluster polygons for given
|
|
52
52
|
points based on a specified minimum distance and minimum points per cluster. Optionally, calculate the relative ratio
|
|
53
53
|
between types of services within the clusters.
|
|
54
54
|
|
|
55
|
-
<img src="https://
|
|
55
|
+
<img src="https://github.com/user-attachments/assets/2a9ad722-87d2-4954-9612-5ac3765aa824" alt="service-clusterization" height="250">
|
|
56
56
|
|
|
57
57
|
## Installation
|
|
58
58
|
|
|
@@ -61,7 +61,16 @@
|
|
|
61
61
|
```
|
|
62
62
|
pip install ObjectNat
|
|
63
63
|
```
|
|
64
|
+
### Configuration changes
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from objectnat import config
|
|
64
68
|
|
|
69
|
+
config.set_timeout(10) # Timeout for overpass queries
|
|
70
|
+
config.change_logger_lvl('INFO') # To mute all debug msgs
|
|
71
|
+
config.set_enable_tqdm(False) # To mute all tqdm's progress bars
|
|
72
|
+
config.set_overpass_url('http://your.overpass-api.de/interpreter/URL')
|
|
73
|
+
```
|
|
65
74
|
## Contacts
|
|
66
75
|
|
|
67
76
|
- [NCCR](https://actcognitive.org/) - National
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "ObjectNat"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0"
|
|
4
4
|
description = "ObjectNat is an open-source library created for geospatial analysis created by IDU team"
|
|
5
5
|
license = "BSD-3-Clause"
|
|
6
|
-
authors = ["
|
|
6
|
+
authors = ["DDonnyy <63115678+DDonnyy@users.noreply.github.com>"]
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
|
|
9
9
|
packages = [{ include = "objectnat", from = "src" }]
|
|
10
10
|
|
|
11
11
|
[tool.poetry.dependencies]
|
|
12
|
-
python = "
|
|
13
|
-
geopandas = "^0.14.3"
|
|
14
|
-
tqdm = "^4.66.2"
|
|
15
|
-
networkit = "^11.0"
|
|
12
|
+
python = ">=3.10,<3.13"
|
|
16
13
|
numpy = "^1.23.5"
|
|
17
14
|
pandas = "^2.2.0"
|
|
15
|
+
geopandas = "^0.14.3"
|
|
16
|
+
tqdm = "^4.66.2"
|
|
17
|
+
pandarallel = "^1.6.5"
|
|
18
18
|
networkx = "^3.2.1"
|
|
19
|
+
networkit = "^11.0"
|
|
20
|
+
pulp = "^2.8.0"
|
|
19
21
|
population-restorator = "^0.2.3"
|
|
20
|
-
|
|
21
|
-
provisio = "^0.1.7"
|
|
22
|
+
iduedu = "^0.1.3"
|
|
22
23
|
joblib = "^1.4.2"
|
|
23
|
-
pandarallel = "^1.6.5"
|
|
24
24
|
scikit-learn = "^1.4.0"
|
|
25
25
|
|
|
26
|
+
|
|
26
27
|
[tool.poetry.group.dev.dependencies]
|
|
27
28
|
black = "^24.2.0"
|
|
28
29
|
pylint = "^3.0.3"
|
|
@@ -46,6 +47,11 @@ disable = [
|
|
|
46
47
|
"duplicate-code",
|
|
47
48
|
"missing-module-docstring",
|
|
48
49
|
"missing-function-docstring",
|
|
50
|
+
"too-many-locals",
|
|
51
|
+
"too-many-branches",
|
|
52
|
+
"too-many-statements",
|
|
53
|
+
"too-many-arguments",
|
|
54
|
+
"cyclic-import"
|
|
49
55
|
]
|
|
50
56
|
good-names = [
|
|
51
57
|
|
|
@@ -59,3 +65,4 @@ use_parentheses = true
|
|
|
59
65
|
ensure_newline_before_comments = true
|
|
60
66
|
line_length = 120
|
|
61
67
|
split_on_trailing_comma = true
|
|
68
|
+
skip = ["__init__.py"]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ObjectNat
|
|
3
|
+
========
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
ObjectNat is an open-source library created for geospatial analysis created by IDU team.
|
|
7
|
+
|
|
8
|
+
Homepage https://github.com/DDonnyy/ObjectNat.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from ._config import config
|
|
12
|
+
from ._api import *
|
|
13
|
+
from ._version import VERSION as __version__
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
# pylint: disable=unused-import,wildcard-import,unused-wildcard-import
|
|
2
|
+
from iduedu import *
|
|
2
3
|
|
|
3
|
-
from dongraphio.enums import GraphType
|
|
4
|
-
|
|
5
|
-
from .methods.adjacency_matrix import get_adjacency_matrix
|
|
6
4
|
from .methods.balanced_buildings import get_balanced_buildings
|
|
7
5
|
from .methods.cluster_points_in_polygons import get_clusters_polygon
|
|
8
6
|
from .methods.coverage_zones import get_isochrone_zone_coverage, get_radius_zone_coverage
|
|
9
|
-
from .methods.demands import get_demands
|
|
10
7
|
from .methods.isochrones import get_accessibility_isochrones
|
|
11
8
|
from .methods.living_buildings_osm import download_buildings
|
|
12
|
-
from .methods.
|
|
13
|
-
from .methods.provision import NoOsmIdException, NoWeightAdjacencyException, get_provision
|
|
9
|
+
from .methods.provision.provision import clip_provision, get_service_provision, recalculate_links
|
|
14
10
|
from .methods.visibility_analysis import (
|
|
15
11
|
calculate_visibility_catchment_area,
|
|
16
12
|
get_visibilities_from_points,
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from typing import Literal
|
|
3
|
+
|
|
4
|
+
from iduedu import config as iduedu_config
|
|
5
|
+
from loguru import logger
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Config:
|
|
9
|
+
"""
|
|
10
|
+
A configuration class to manage global settings for the application, such as Overpass API URL,
|
|
11
|
+
timeouts, and logging options.
|
|
12
|
+
|
|
13
|
+
Attributes
|
|
14
|
+
----------
|
|
15
|
+
overpass_url : str
|
|
16
|
+
URL for accessing the Overpass API. Defaults to "http://lz4.overpass-api.de/api/interpreter".
|
|
17
|
+
timeout : int or None
|
|
18
|
+
Timeout in seconds for API requests. If None, no timeout is applied.
|
|
19
|
+
enable_tqdm_bar : bool
|
|
20
|
+
Enables or disables progress bars (via tqdm). Defaults to True.
|
|
21
|
+
logger : Logger
|
|
22
|
+
Logging instance to handle application logging.
|
|
23
|
+
|
|
24
|
+
Methods
|
|
25
|
+
-------
|
|
26
|
+
change_logger_lvl(lvl: Literal["TRACE", "DEBUG", "INFO", "WARN", "ERROR"])
|
|
27
|
+
Changes the logging level to the specified value.
|
|
28
|
+
set_overpass_url(url: str)
|
|
29
|
+
Sets a new Overpass API URL.
|
|
30
|
+
set_timeout(timeout: int)
|
|
31
|
+
Sets the timeout for API requests.
|
|
32
|
+
set_enable_tqdm(enable: bool)
|
|
33
|
+
Enables or disables progress bars in the application.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
overpass_url="http://lz4.overpass-api.de/api/interpreter",
|
|
39
|
+
timeout=None,
|
|
40
|
+
enable_tqdm_bar=True,
|
|
41
|
+
):
|
|
42
|
+
self.overpass_url = overpass_url
|
|
43
|
+
self.timeout = timeout
|
|
44
|
+
self.enable_tqdm_bar = enable_tqdm_bar
|
|
45
|
+
self.logger = logger
|
|
46
|
+
self.iduedu_config = iduedu_config
|
|
47
|
+
|
|
48
|
+
def change_logger_lvl(self, lvl: Literal["TRACE", "DEBUG", "INFO", "WARN", "ERROR"]):
|
|
49
|
+
self.logger.remove()
|
|
50
|
+
self.logger.add(sys.stderr, level=lvl)
|
|
51
|
+
self.iduedu_config.change_logger_lvl(lvl)
|
|
52
|
+
|
|
53
|
+
def set_overpass_url(self, url: str):
|
|
54
|
+
self.overpass_url = url
|
|
55
|
+
self.iduedu_config.set_overpass_url(url)
|
|
56
|
+
|
|
57
|
+
def set_timeout(self, timeout: int):
|
|
58
|
+
self.timeout = timeout
|
|
59
|
+
self.iduedu_config.set_timeout(timeout)
|
|
60
|
+
|
|
61
|
+
def set_enable_tqdm(self, enable: bool):
|
|
62
|
+
self.enable_tqdm_bar = enable
|
|
63
|
+
self.iduedu_config.set_enable_tqdm(enable)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
config = Config()
|
|
67
|
+
config.change_logger_lvl("INFO")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "0.2.0"
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import geopandas as gpd
|
|
2
2
|
import population_restorator.balancer.houses as b_build
|
|
3
3
|
import population_restorator.balancer.territories as b_terr
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
from objectnat import config
|
|
6
|
+
|
|
7
|
+
logger = config.logger
|
|
5
8
|
|
|
6
9
|
|
|
7
10
|
def get_balanced_buildings(
|
|
@@ -2,9 +2,12 @@ from typing import Literal
|
|
|
2
2
|
|
|
3
3
|
import geopandas as gpd
|
|
4
4
|
import pandas as pd
|
|
5
|
-
from loguru import logger
|
|
6
5
|
from sklearn.cluster import DBSCAN, HDBSCAN
|
|
7
6
|
|
|
7
|
+
from objectnat import config
|
|
8
|
+
|
|
9
|
+
logger = config.logger
|
|
10
|
+
|
|
8
11
|
|
|
9
12
|
def _get_cluster(services_select, min_dist, min_point, method):
|
|
10
13
|
services_coords = pd.DataFrame(
|
|
@@ -2,8 +2,6 @@ from typing import Literal
|
|
|
2
2
|
|
|
3
3
|
import geopandas as gpd
|
|
4
4
|
import networkx as nx
|
|
5
|
-
import pandas as pd
|
|
6
|
-
from dongraphio import GraphType
|
|
7
5
|
|
|
8
6
|
from .isochrones import get_accessibility_isochrones
|
|
9
7
|
|
|
@@ -48,7 +46,6 @@ def get_isochrone_zone_coverage(
|
|
|
48
46
|
weight_type: Literal["time_min", "length_meter"],
|
|
49
47
|
weight_value: int,
|
|
50
48
|
city_graph: nx.Graph,
|
|
51
|
-
graph_type: list[GraphType],
|
|
52
49
|
) -> tuple[gpd.GeoDataFrame, gpd.GeoDataFrame | None, gpd.GeoDataFrame | None]:
|
|
53
50
|
"""
|
|
54
51
|
Create isochrones for each service location based on travel time/distance.
|
|
@@ -56,15 +53,13 @@ def get_isochrone_zone_coverage(
|
|
|
56
53
|
Parameters
|
|
57
54
|
----------
|
|
58
55
|
services : gpd.GeoDataFrame
|
|
59
|
-
|
|
56
|
+
Layer containing the service locations.
|
|
60
57
|
weight_type : str
|
|
61
58
|
Type of weight used for calculating isochrones, either "time_min" or "length_meter".
|
|
62
59
|
weight_value : int
|
|
63
60
|
The value of the weight, representing time in minutes or distance in meters.
|
|
64
61
|
city_graph : nx.Graph
|
|
65
62
|
The graph representing the city's transportation network.
|
|
66
|
-
graph_type : list[GraphType]
|
|
67
|
-
List of graph types to be used for isochrone calculations.
|
|
68
63
|
|
|
69
64
|
Returns
|
|
70
65
|
-------
|
|
@@ -76,10 +71,10 @@ def get_isochrone_zone_coverage(
|
|
|
76
71
|
>>> import networkx as nx
|
|
77
72
|
>>> import geopandas as gpd
|
|
78
73
|
>>> from shapely.geometry import Point
|
|
79
|
-
|
|
74
|
+
>>> from iduedu import get_intermodal_graph
|
|
80
75
|
|
|
81
|
-
>>> # Create a sample city graph
|
|
82
|
-
>>>
|
|
76
|
+
>>> # Create a sample city graph with get_intermodal_graph()
|
|
77
|
+
>>> graph = get_intermodal_graph(polygon=my_territory_polygon)
|
|
83
78
|
|
|
84
79
|
>>> # Create a sample GeoDataFrame for services
|
|
85
80
|
>>> services = gpd.read_file('services.geojson')
|
|
@@ -87,19 +82,9 @@ def get_isochrone_zone_coverage(
|
|
|
87
82
|
>>> # Define parameters
|
|
88
83
|
>>> weight_type = "time_min"
|
|
89
84
|
>>> weight_value = 10
|
|
90
|
-
>>> graph_type = [GraphType.PUBLIC_TRANSPORT, GraphType.WALK]
|
|
91
85
|
|
|
92
86
|
>>> # Get isochrone zone coverage
|
|
93
|
-
>>>
|
|
94
|
-
>>> isochrone_zones[0] # represent isochrones geodataframe
|
|
87
|
+
>>> isochrones, pt_stops, pt_routes = get_isochrone_zone_coverage(services, weight_type, weight_value, city_graph)
|
|
95
88
|
"""
|
|
96
|
-
|
|
97
|
-
points = services.geometry.representative_point()
|
|
98
|
-
iso, routes, stops = get_accessibility_isochrones(
|
|
99
|
-
points, graph_type, weight_value, weight_type, city_graph, points.crs.to_epsg()
|
|
100
|
-
)
|
|
101
|
-
services_ = services.copy()
|
|
102
|
-
iso = gpd.GeoDataFrame(
|
|
103
|
-
pd.concat([iso.drop(columns=["point", "point_number"]), services_.drop(columns=["geometry"])], axis=1)
|
|
104
|
-
)
|
|
89
|
+
iso, routes, stops = get_accessibility_isochrones(services, weight_value, weight_type, city_graph)
|
|
105
90
|
return iso, routes, stops
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
3
|
+
import geopandas as gpd
|
|
4
|
+
import networkx as nx
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
from osmnx import graph_to_gdfs
|
|
8
|
+
from pyproj import CRS
|
|
9
|
+
from scipy.spatial import KDTree
|
|
10
|
+
from shapely import Point
|
|
11
|
+
from shapely.ops import unary_union
|
|
12
|
+
|
|
13
|
+
from objectnat import config
|
|
14
|
+
|
|
15
|
+
logger = config.logger
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_accessibility_isochrones(
|
|
19
|
+
points: gpd.GeoDataFrame,
|
|
20
|
+
weight_value: float,
|
|
21
|
+
weight_type: Literal["time_min", "length_meter"],
|
|
22
|
+
graph_nx: nx.Graph,
|
|
23
|
+
) -> tuple[gpd.GeoDataFrame, gpd.GeoDataFrame | None, gpd.GeoDataFrame | None]:
|
|
24
|
+
"""
|
|
25
|
+
Calculate accessibility isochrones from a gpd.GeoDataFrame based on the provided city graph.
|
|
26
|
+
|
|
27
|
+
Isochrones represent areas that can be reached from a given point within a specific time or distance,
|
|
28
|
+
using a graph that contains road and transport network data.
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
points : gpd.GeoDataFrame
|
|
33
|
+
A GeoDataFrame containing the geometry from which accessibility isochrones should be calculated.
|
|
34
|
+
The CRS of this GeoDataFrame must match the CRS of the provided graph.
|
|
35
|
+
weight_value : float
|
|
36
|
+
The maximum distance or time threshold for calculating isochrones.
|
|
37
|
+
weight_type : Literal["time_min", "length_meter"]
|
|
38
|
+
The type of weight to use for distance calculations. Either time in minutes ("time_min") or distance
|
|
39
|
+
in meters ("length_meter").
|
|
40
|
+
graph_nx : nx.Graph
|
|
41
|
+
A NetworkX graph representing the city network.
|
|
42
|
+
The graph must contain the appropriate CRS and, for time-based isochrones, a speed attribute.
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
tuple[gpd.GeoDataFrame, gpd.GeoDataFrame | None, gpd.GeoDataFrame | None]
|
|
47
|
+
A tuple containing:
|
|
48
|
+
- isochrones : GeoDataFrame with the calculated isochrone geometries.
|
|
49
|
+
- public transport stops (if applicable) : GeoDataFrame with public transport stops within the isochrone, or None if not applicable.
|
|
50
|
+
- public transport routes (if applicable) : GeoDataFrame with public transport routes within the isochrone, or None if not applicable.
|
|
51
|
+
|
|
52
|
+
Examples
|
|
53
|
+
--------
|
|
54
|
+
>>> from iduedu import get_intermodal_graph
|
|
55
|
+
>>> graph = get_intermodal_graph(polygon=my_territory_polygon)
|
|
56
|
+
>>> points = gpd.GeoDataFrame(geometry=[Point(30.33, 59.95)], crs=4326).to_crs(graph.graph['crs'])
|
|
57
|
+
>>> isochrones, pt_stops, pt_routes = get_accessibility_isochrones(points, weight_value=15, weight_type="time_min", graph_nx=my_graph)
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
assert points.crs == CRS.from_epsg(
|
|
62
|
+
graph_nx.graph["crs"]
|
|
63
|
+
), f'CRS mismatch , points.crs = {points.crs.to_epsg()}, graph["crs"] = {graph_nx.graph["crs"]}'
|
|
64
|
+
|
|
65
|
+
nodes_with_data = list(graph_nx.nodes(data=True))
|
|
66
|
+
logger.info("Calculating isochrones distances...")
|
|
67
|
+
coordinates = np.array([(data["x"], data["y"]) for node, data in nodes_with_data])
|
|
68
|
+
tree = KDTree(coordinates)
|
|
69
|
+
|
|
70
|
+
target_coord = [(p.x, p.y) for p in points.representative_point()]
|
|
71
|
+
distances, indices = tree.query(target_coord)
|
|
72
|
+
|
|
73
|
+
nearest_nodes = [nodes_with_data[idx][0] for idx in indices]
|
|
74
|
+
del nodes_with_data
|
|
75
|
+
dist_nearest = pd.DataFrame(data=distances, index=nearest_nodes, columns=["dist"])
|
|
76
|
+
speed = 0
|
|
77
|
+
if graph_nx.graph["type"] in ["walk", "intermodal"] and weight_type == "time_min":
|
|
78
|
+
try:
|
|
79
|
+
speed = graph_nx.graph["walk_speed"]
|
|
80
|
+
except KeyError:
|
|
81
|
+
logger.warning("There is no walk_speed in graph, set to the default speed - 83.33 m/min")
|
|
82
|
+
speed = 83.33
|
|
83
|
+
dist_nearest = dist_nearest / speed
|
|
84
|
+
elif weight_type == "time_min":
|
|
85
|
+
speed = 20 * 1000 / 60
|
|
86
|
+
dist_nearest = dist_nearest / speed
|
|
87
|
+
|
|
88
|
+
if (dist_nearest > weight_value).all().all():
|
|
89
|
+
raise RuntimeError(
|
|
90
|
+
"The point(s) lie further from the graph than weight_value, it's impossible to "
|
|
91
|
+
"construct isochrones. Check the coordinates of the point(s)/their projection"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
data = []
|
|
95
|
+
for source in nearest_nodes:
|
|
96
|
+
dist, path = nx.single_source_dijkstra(graph_nx, source, weight=weight_type, cutoff=weight_value)
|
|
97
|
+
for target_node, way in path.items():
|
|
98
|
+
source = way[0]
|
|
99
|
+
distance = dist.get(target_node, np.nan)
|
|
100
|
+
data.append((source, target_node, distance))
|
|
101
|
+
del dist
|
|
102
|
+
dist_matrix = pd.DataFrame(data, columns=["source", "destination", "distance"])
|
|
103
|
+
del data
|
|
104
|
+
dist_matrix = dist_matrix.pivot_table(index="source", columns="destination", values="distance", sort=False)
|
|
105
|
+
|
|
106
|
+
dist_matrix = dist_matrix.add(dist_nearest.dist, axis=0)
|
|
107
|
+
dist_matrix = dist_matrix.mask(dist_matrix >= weight_value, np.nan)
|
|
108
|
+
dist_matrix.dropna(how="all", inplace=True)
|
|
109
|
+
|
|
110
|
+
results = []
|
|
111
|
+
logger.info("Building isochrones geometry...")
|
|
112
|
+
for _, row in dist_matrix.iterrows():
|
|
113
|
+
geometry = []
|
|
114
|
+
for node_to, value in row.items():
|
|
115
|
+
if not pd.isna(value):
|
|
116
|
+
node = graph_nx.nodes[node_to]
|
|
117
|
+
point = Point(node["x"], node["y"])
|
|
118
|
+
geometry.append(
|
|
119
|
+
point.buffer(round((weight_value - value) * speed * 0.8, 2))
|
|
120
|
+
if weight_type == "time_min"
|
|
121
|
+
else point.buffer(round((weight_value - value) * 0.8, 2))
|
|
122
|
+
)
|
|
123
|
+
geometry = unary_union(geometry)
|
|
124
|
+
results.append(geometry)
|
|
125
|
+
|
|
126
|
+
isochrones = gpd.GeoDataFrame(data=points, geometry=results, crs=graph_nx.graph["crs"])
|
|
127
|
+
isochrones["weight_type"] = weight_type
|
|
128
|
+
isochrones["weight_value"] = weight_value
|
|
129
|
+
|
|
130
|
+
isochrones_subgraph = graph_nx.subgraph(dist_matrix.columns)
|
|
131
|
+
nodes = pd.DataFrame.from_dict(dict(isochrones_subgraph.nodes(data=True)), orient="index")
|
|
132
|
+
if "desc" in nodes.columns and "stop" in nodes["desc"].unique():
|
|
133
|
+
pt_nodes = nodes[nodes["desc"] == "stop"]
|
|
134
|
+
nodes, edges = graph_to_gdfs(isochrones_subgraph.subgraph(pt_nodes.index))
|
|
135
|
+
nodes.reset_index(drop=True, inplace=True)
|
|
136
|
+
nodes = nodes[["desc", "route", "geometry"]]
|
|
137
|
+
edges.reset_index(drop=True, inplace=True)
|
|
138
|
+
edges = edges[["type", "route", "geometry"]]
|
|
139
|
+
return isochrones, nodes, edges
|
|
140
|
+
return isochrones, None, None
|