ObjectNat 0.1.5__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.

Files changed (26) hide show
  1. {objectnat-0.1.5 → objectnat-0.2.1}/PKG-INFO +35 -21
  2. {objectnat-0.1.5 → objectnat-0.2.1}/README.md +30 -16
  3. {objectnat-0.1.5 → objectnat-0.2.1}/pyproject.toml +16 -9
  4. objectnat-0.2.1/src/objectnat/__init__.py +13 -0
  5. objectnat-0.1.5/src/objectnat/__init__.py → objectnat-0.2.1/src/objectnat/_api.py +3 -7
  6. objectnat-0.2.1/src/objectnat/_config.py +67 -0
  7. objectnat-0.2.1/src/objectnat/_version.py +1 -0
  8. {objectnat-0.1.5 → objectnat-0.2.1}/src/objectnat/methods/balanced_buildings.py +4 -1
  9. {objectnat-0.1.5 → objectnat-0.2.1}/src/objectnat/methods/cluster_points_in_polygons.py +4 -1
  10. {objectnat-0.1.5 → objectnat-0.2.1}/src/objectnat/methods/coverage_zones.py +6 -21
  11. objectnat-0.2.1/src/objectnat/methods/isochrones.py +140 -0
  12. {objectnat-0.1.5 → objectnat-0.2.1}/src/objectnat/methods/living_buildings_osm.py +24 -94
  13. objectnat-0.2.1/src/objectnat/methods/provision/__init__.py +0 -0
  14. objectnat-0.2.1/src/objectnat/methods/provision/city_provision.py +325 -0
  15. objectnat-0.2.1/src/objectnat/methods/provision/provision.py +90 -0
  16. objectnat-0.2.1/src/objectnat/methods/provision/provision_exceptions.py +59 -0
  17. {objectnat-0.1.5 → objectnat-0.2.1}/src/objectnat/methods/visibility_analysis.py +4 -1
  18. objectnat-0.1.5/src/objectnat/methods/adjacency_matrix.py +0 -39
  19. objectnat-0.1.5/src/objectnat/methods/demands.py +0 -43
  20. objectnat-0.1.5/src/objectnat/methods/isochrones.py +0 -66
  21. objectnat-0.1.5/src/objectnat/methods/osm_graph.py +0 -23
  22. objectnat-0.1.5/src/objectnat/methods/provision.py +0 -135
  23. {objectnat-0.1.5 → objectnat-0.2.1}/LICENSE.txt +0 -0
  24. {objectnat-0.1.5 → objectnat-0.2.1}/src/objectnat/methods/__init__.py +0 -0
  25. {objectnat-0.1.5 → objectnat-0.2.1}/src/objectnat/utils/__init__.py +0 -0
  26. {objectnat-0.1.5 → objectnat-0.2.1}/src/objectnat/utils/utils.py +0 -0
@@ -1,18 +1,18 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ObjectNat
3
- Version: 0.1.5
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
- Author: Danila
6
+ Author: DDonnyy
7
7
  Author-email: 63115678+DDonnyy@users.noreply.github.com
8
- Requires-Python: >=3.10,<4.0
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.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)
@@ -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: provisio (>=0.1.7,<0.2.0)
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,59 +28,64 @@ Description-Content-Type: text/markdown
28
28
  # ObjectNat - Meta Library
29
29
 
30
30
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
31
+ [![PyPI version](https://img.shields.io/pypi/v/objectnat.svg)](https://pypi.org/project/objectnat/)
31
32
 
33
+ - [РИДМИ (Russian)](README_ru.md)
32
34
  <p align="center">
33
- <img src="https://i.ibb.co/FWtHNQv/logo.png" alt="logo" width="400">
35
+ <img src="https://github.com/user-attachments/assets/d3878cce-8eba-4f96-8458-9a798d436120" alt="logo" width="400">
34
36
  </p>
35
37
 
36
38
  #### **ObjectNat** is an open-source library created for geospatial analysis created by **IDU team**
37
39
 
38
40
  ## ObjectNat Components
39
41
 
40
- - [dongraphio](https://github.com/DDonnyy/dongraphio) : `dongraphio` provides graph functions
41
- - [provisio](https://github.com/DDonnyy/provisio) : `provisio` provides main provisio fuctions
42
+ - [IduEdu](https://github.com/DDonnyy/IduEdu) : `IduEdu` provides graph functions
42
43
  - [population-restorator](https://github.com/kanootoko/population-restorator) : `restorator` provides city resettlement
43
44
 
44
45
  ## Features and how to use
45
46
 
46
- 1. **[City graph from OSM](./examples/graph_generator.ipynb)** - Function to assemble a road, pedestrian, and public
47
- transport graph from OpenStreetMap (OSM) and creating Intermodal graph.
47
+ 1. **[City graph from OSM (IduEdu)](https://github.com/DDonnyy/IduEdu/blob/main/examples/get_any_graph.ipynb)** - Functions to assemble a road, pedestrian,
48
+ and public transport graph from OpenStreetMap (OSM) and creating Intermodal graph.
48
49
 
49
- <img src="https://i.ibb.co/VpsPgL1/Graph-generator-v1.webp" alt="Graph-generator-v1" height="250">
50
+ <img src="https://github.com/user-attachments/assets/8dc98da9-8462-415e-8cc8-bdfca788e206" alt="IntermodalGraph" height="250">
50
51
 
51
52
  2. **[Adjacency matrix](./examples/calculate_adjacency_matrix.ipynb)** - Calculate adjacency matrix based on the provided
52
53
  graph and edge weight type (time or distance). The intermodal graph can be obtained using the previous example.
54
+
53
55
  3. **[Isochrones,transport accessibility](./examples/isochrone_generator.ipynb)** - Function for generating isochrones to
54
56
  analyze transportation accessibility from specified starting coordinates. Isochrones can be constructed based on
55
57
  pedestrian, automobile, or public transport graphs, or a combination thereof.
56
58
 
57
- <img src="https://i.ibb.co/QM0tmZ2/isochrones-from-2-points.webp" alt="isochrones-from-2-points" height="250">
59
+ <img src="https://github.com/user-attachments/assets/37f308a5-db56-497d-b080-4edef3584fe5" alt="isochrones" height="250">
58
60
 
59
61
  4. **[Population restoration](./examples/restore_population.ipynb)** - Function for resettling population into the provided
60
62
  layer of residential buildings. This function distributes people among dwellings based on the total city population
61
63
  and the living area of each house.
62
64
  5. **[Service provision](./examples/calculate_provision.ipynb)** - Function for calculating the provision of residential
63
- buildings and population with services. In case of missing data, this function utilizes previously described
64
- functionality to retrieve the necessary information.
65
+ buildings and population with services.
66
+
67
+ <img src="https://github.com/user-attachments/assets/5f2b3c55-9a02-4d70-80f4-503b77023eda" alt="ProvisionSchools" height="250">
65
68
 
66
- <img src="https://i.ibb.co/CW7Xj5F/Burger-Provision5min.webp" alt="Burger-Provision5min" height="250">
67
-
68
69
  6. **[Visibility analysis](./examples/visibility_analysis.ipynb)** - Function to get a quick estimate of visibility from a
69
70
  given point(s) to buildings within a given distance. Also, there is a visibility catchment area calculator for a
70
71
  large
71
72
  urban area. This function is designed to work with at least 1000 points spaced 10-20 meters apart for optimal
72
73
  results. Points can be generated using a road graph and random point distribution along edges.
73
74
 
74
- <img src="https://i.ibb.co/LxcGTfN/visibility-from-point.webp" alt="visibility-from-point" height="250">
75
-
76
- <img src="https://i.ibb.co/zNRzXc5/visibility-catchment-area.webp" alt="visibility-catchment-area" height="250">
75
+ <img src="https://github.com/user-attachments/assets/2927ac86-01e8-4b0e-9ea8-72ad81c13cf5" alt="visibility-from-point" height="250">
77
76
 
77
+ <img src="https://github.com/user-attachments/assets/b5b0d4b3-a02f-4ade-8772-475703cd6435" alt="visibility-catchment-area" height="250">
78
+
78
79
  7. **[Point clusterization](./examples/point_clusterization.ipynb)** - Function to generate cluster polygons for given
79
80
  points based on a specified minimum distance and minimum points per cluster. Optionally, calculate the relative ratio
80
81
  between types of services within the clusters.
81
82
 
82
- <img src="https://i.ibb.co/fF3c4YC/service-clusterization.webp" alt="service-clusterization" height="250">
83
-
83
+ <img src="https://github.com/user-attachments/assets/2a9ad722-87d2-4954-9612-5ac3765aa824" alt="service-clusterization" height="250">
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``:
@@ -88,7 +93,16 @@ Description-Content-Type: text/markdown
88
93
  ```
89
94
  pip install ObjectNat
90
95
  ```
96
+ ### Configuration changes
91
97
 
98
+ ```python
99
+ from objectnat import config
100
+
101
+ config.set_timeout(10) # Timeout for overpass queries
102
+ config.change_logger_lvl('INFO') # To mute all debug msgs
103
+ config.set_enable_tqdm(False) # To mute all tqdm's progress bars
104
+ config.set_overpass_url('http://your.overpass-api.de/interpreter/URL')
105
+ ```
92
106
  ## Contacts
93
107
 
94
108
  - [NCCR](https://actcognitive.org/) - National
@@ -1,59 +1,64 @@
1
1
  # ObjectNat - Meta Library
2
2
 
3
3
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
4
+ [![PyPI version](https://img.shields.io/pypi/v/objectnat.svg)](https://pypi.org/project/objectnat/)
4
5
 
6
+ - [РИДМИ (Russian)](README_ru.md)
5
7
  <p align="center">
6
- <img src="https://i.ibb.co/FWtHNQv/logo.png" alt="logo" width="400">
8
+ <img src="https://github.com/user-attachments/assets/d3878cce-8eba-4f96-8458-9a798d436120" alt="logo" width="400">
7
9
  </p>
8
10
 
9
11
  #### **ObjectNat** is an open-source library created for geospatial analysis created by **IDU team**
10
12
 
11
13
  ## ObjectNat Components
12
14
 
13
- - [dongraphio](https://github.com/DDonnyy/dongraphio) : `dongraphio` provides graph functions
14
- - [provisio](https://github.com/DDonnyy/provisio) : `provisio` provides main provisio fuctions
15
+ - [IduEdu](https://github.com/DDonnyy/IduEdu) : `IduEdu` provides graph functions
15
16
  - [population-restorator](https://github.com/kanootoko/population-restorator) : `restorator` provides city resettlement
16
17
 
17
18
  ## Features and how to use
18
19
 
19
- 1. **[City graph from OSM](./examples/graph_generator.ipynb)** - Function to assemble a road, pedestrian, and public
20
- transport graph from OpenStreetMap (OSM) and creating Intermodal graph.
20
+ 1. **[City graph from OSM (IduEdu)](https://github.com/DDonnyy/IduEdu/blob/main/examples/get_any_graph.ipynb)** - Functions to assemble a road, pedestrian,
21
+ and public transport graph from OpenStreetMap (OSM) and creating Intermodal graph.
21
22
 
22
- <img src="https://i.ibb.co/VpsPgL1/Graph-generator-v1.webp" alt="Graph-generator-v1" height="250">
23
+ <img src="https://github.com/user-attachments/assets/8dc98da9-8462-415e-8cc8-bdfca788e206" alt="IntermodalGraph" height="250">
23
24
 
24
25
  2. **[Adjacency matrix](./examples/calculate_adjacency_matrix.ipynb)** - Calculate adjacency matrix based on the provided
25
26
  graph and edge weight type (time or distance). The intermodal graph can be obtained using the previous example.
27
+
26
28
  3. **[Isochrones,transport accessibility](./examples/isochrone_generator.ipynb)** - Function for generating isochrones to
27
29
  analyze transportation accessibility from specified starting coordinates. Isochrones can be constructed based on
28
30
  pedestrian, automobile, or public transport graphs, or a combination thereof.
29
31
 
30
- <img src="https://i.ibb.co/QM0tmZ2/isochrones-from-2-points.webp" alt="isochrones-from-2-points" height="250">
32
+ <img src="https://github.com/user-attachments/assets/37f308a5-db56-497d-b080-4edef3584fe5" alt="isochrones" height="250">
31
33
 
32
34
  4. **[Population restoration](./examples/restore_population.ipynb)** - Function for resettling population into the provided
33
35
  layer of residential buildings. This function distributes people among dwellings based on the total city population
34
36
  and the living area of each house.
35
37
  5. **[Service provision](./examples/calculate_provision.ipynb)** - Function for calculating the provision of residential
36
- buildings and population with services. In case of missing data, this function utilizes previously described
37
- functionality to retrieve the necessary information.
38
+ buildings and population with services.
39
+
40
+ <img src="https://github.com/user-attachments/assets/5f2b3c55-9a02-4d70-80f4-503b77023eda" alt="ProvisionSchools" height="250">
38
41
 
39
- <img src="https://i.ibb.co/CW7Xj5F/Burger-Provision5min.webp" alt="Burger-Provision5min" height="250">
40
-
41
42
  6. **[Visibility analysis](./examples/visibility_analysis.ipynb)** - Function to get a quick estimate of visibility from a
42
43
  given point(s) to buildings within a given distance. Also, there is a visibility catchment area calculator for a
43
44
  large
44
45
  urban area. This function is designed to work with at least 1000 points spaced 10-20 meters apart for optimal
45
46
  results. Points can be generated using a road graph and random point distribution along edges.
46
47
 
47
- <img src="https://i.ibb.co/LxcGTfN/visibility-from-point.webp" alt="visibility-from-point" height="250">
48
-
49
- <img src="https://i.ibb.co/zNRzXc5/visibility-catchment-area.webp" alt="visibility-catchment-area" height="250">
48
+ <img src="https://github.com/user-attachments/assets/2927ac86-01e8-4b0e-9ea8-72ad81c13cf5" alt="visibility-from-point" height="250">
50
49
 
50
+ <img src="https://github.com/user-attachments/assets/b5b0d4b3-a02f-4ade-8772-475703cd6435" alt="visibility-catchment-area" height="250">
51
+
51
52
  7. **[Point clusterization](./examples/point_clusterization.ipynb)** - Function to generate cluster polygons for given
52
53
  points based on a specified minimum distance and minimum points per cluster. Optionally, calculate the relative ratio
53
54
  between types of services within the clusters.
54
55
 
55
- <img src="https://i.ibb.co/fF3c4YC/service-clusterization.webp" alt="service-clusterization" height="250">
56
-
56
+ <img src="https://github.com/user-attachments/assets/2a9ad722-87d2-4954-9612-5ac3765aa824" alt="service-clusterization" height="250">
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``:
@@ -61,7 +66,16 @@
61
66
  ```
62
67
  pip install ObjectNat
63
68
  ```
69
+ ### Configuration changes
64
70
 
71
+ ```python
72
+ from objectnat import config
73
+
74
+ config.set_timeout(10) # Timeout for overpass queries
75
+ config.change_logger_lvl('INFO') # To mute all debug msgs
76
+ config.set_enable_tqdm(False) # To mute all tqdm's progress bars
77
+ config.set_overpass_url('http://your.overpass-api.de/interpreter/URL')
78
+ ```
65
79
  ## Contacts
66
80
 
67
81
  - [NCCR](https://actcognitive.org/) - National
@@ -1,28 +1,29 @@
1
1
  [tool.poetry]
2
2
  name = "ObjectNat"
3
- version = "0.1.5"
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
- authors = ["Danila <63115678+DDonnyy@users.noreply.github.com>"]
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 = "^3.10"
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
- dongraphio = "^0.3.13"
21
- provisio = "^0.1.7"
22
+ iduedu = "^0.1.4"
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
- __version__ = "0.1.5"
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.osm_graph import get_intermodal_graph_from_osm
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.1"
@@ -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
- from loguru import logger
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
- GeoDataFrame containing the service locations.
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
- >>> from dongraphio import GraphType
74
+ >>> from iduedu import get_intermodal_graph
80
75
 
81
- >>> # Create a sample city graph or download it from osm with get_intermodal_graph_from_osm()
82
- >>> city_graph = nx.MultiDiGraph()
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
- >>> isochrone_zones = get_isochrone_zone_coverage(services, weight_type, weight_value, city_graph, graph_type)
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
- assert services.crs == city_graph.graph["crs"], "CRS not match"
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