-
-#### **ObjectNat** is an open-source library created for geospatial analysis created by **IDU team**
-
----
-
-## Features and How to Use
-
-Each feature is accompanied by a Jupyter notebook example and full documentation.
-
-1. **[Isochrones and Transport Accessibility](./examples/isochrone_generator.ipynb)**
- Analyze areas reachable within a given time along a transport network.
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/isochrones.html)
-
-2. **[Coverage Zones](./examples/coverage_zones.ipynb)**
- Build zones of reachability for each point using routing or simple radius.
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/coverage.html)
-
-3. **[Service Provision Analysis](./examples/calculate_provision.ipynb)**
- Evaluate service availability and model demand-supply balance.
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/provision.html)
-
-4. **[Visibility Analysis](./examples/visibility_analysis.ipynb)**
- Estimate visibility to nearby buildings from selected points.
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/visibility.html)
-
-5. **[Noise Simulation](./examples/noise_simulation.ipynb)**
- Simulate noise propagation considering obstacles and environment.
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/noise.html)
- 🔗 [Detailed theory in the Wiki](https://github.com/DDonnyy/ObjectNat/wiki/Noise-simulation)
-
-6. **[Point Clusterization](./examples/point_clusterization.ipynb)**
- Group nearby points into clusters and analyze service composition.
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/clustering.html)
-
----
-
-## City graphs
-
-To ensure optimal performance of ObjectNat's geospatial analysis functions, it's recommended to utilize urban graphs sourced from the [IduEdu](https://github.com/DDonnyy/IduEdu) library.
-**IduEdu** is an open-source Python library designed for the creation and manipulation of complex city networks derived from OpenStreetMap data.
-
-**IduEdu** can be installed with ``pip``:
-```
-pip install IduEdu
-```
----
-
-## Installation
-
-**ObjectNat** can be installed with ``pip``:
-
-```
-pip install ObjectNat
-```
-
----
-
-### Configuration changes
-
-```python
-from objectnat import config
-
-config.change_logger_lvl('INFO') # To mute all debug msgs
-config.set_enable_tqdm(False) # To mute all tqdm's progress bars
-```
-
----
-
-## Contacts
-
-- [NCCR](https://actcognitive.org/) - National Center for Cognitive Research
-- [IDU](https://idu.itmo.ru/) - Institute of Design and Urban Studies
-- [Natalya Chichkova](https://t.me/nancy_nat) - project manager
-- [Danila Oleynikov (Donny)](https://t.me/ddonny_dd) - lead software engineer
-
----
-
-## Publications
-
-_Coming soon._
\ No newline at end of file
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..9a040ff
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,176 @@
+ObjectNat
+=========
+
+Object-oriented Network Analysis Tools
+--------------------------------------
+
+.. |badge-black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
+ :target: https://github.com/psf/black
+ :alt: Code style: black
+
+.. |badge-pypi| image:: https://img.shields.io/pypi/v/objectnat.svg
+ :target: https://pypi.org/project/objectnat/
+ :alt: PyPI version
+
+.. |badge-ci| image:: https://github.com/IDUclub/ObjectNat/actions/workflows/ci_pipeline.yml/badge.svg
+ :target: https://github.com/IDUclub/ObjectNat/actions/workflows/ci_pipeline.yml
+ :alt: CI
+
+.. |badge-codecov| image:: https://codecov.io/gh/DDonnyy/ObjectNat/graph/badge.svg?token=K6JFSJ02GU
+ :target: https://codecov.io/gh/DDonnyy/ObjectNat
+ :alt: Coverage
+
+.. |badge-license| image:: https://img.shields.io/badge/license-BSD--3--Clause-blue.svg
+ :target: https://opensource.org/licenses/BSD-3-Clause
+ :alt: License
+
+|badge-black| |badge-pypi| |badge-ci| |badge-codecov| |badge-license|
+
+`РИДМИ (Russian) `_
+
+.. raw:: html
+
+
+
+
+
+
+**ObjectNat** is an open-source library developed by the **IDU** team
+for spatial and network analysis in urban studies.
+The library provides tools for analyzing **accessibility**, **visibility**,
+**noise propagation**, and **service provision**.
+----
+
+Key Features
+------------
+
+Each feature includes a **Jupyter Notebook example** and **full documentation**.
+
+1. **Isochrones and Transport Accessibility**
+
+ Isochrones represent areas reachable from an origin point within a specified time along a transport network.
+ This feature allows the analysis of transport accessibility using pedestrian, road,
+ public transport, or multimodal graphs.
+
+ The library supports several methods for building isochrones:
+
+ - **Basic isochrones**: display a single zone reachable within a specified time.
+ - **Step isochrones**: divide the accessibility area into time intervals (e.g., 3, 5, 10 minutes).
+
+
+ 📘 `Example `_
+ 🔗 `Documentation `_
+
+2. **Graph Coverage Zones from Points**
+
+ A function for generating **coverage areas** from a set of origin points using a transport network.
+ It computes the area reachable from each point by **travel time** or **distance**,
+ then builds polygons using **Voronoi diagrams** and clips them by a given boundary if specified.
+
+ 📘 `Example `_
+ 🔗 `Documentation `_
+
+3. **Service Provision Analysis**
+
+ A function to evaluate how well residential buildings and their populations are provided
+ with services (e.g., schools, clinics) that have limited **capacity**
+ and a defined **accessibility threshold** (in minutes or meters).
+ The function models the **balance between supply and demand**,
+ assessing how well services meet the needs of nearby buildings within an acceptable time.
+
+ 📘 `Example `_
+ 🔗 `Documentation `_
+
+4. **Visibility Analysis**
+
+ A function for evaluating visibility from a given point or set of points to nearby buildings within a given radius.
+ It is used to assess visual accessibility in urban environments.
+ A module is also implemented for computing **visibility coverage zones**
+ using a dense observer grid (recommended ~1000 points with a 10–20 m spacing).
+ Points can be generated along the transport network and distributed across its edges.
+
+ 📘 `Example `_
+ 🔗 `Documentation `_
+
+5. **Noise Simulation & Noise Frame**
+
+ Simulation of noise propagation from sources, taking into account **obstacles**, **vegetation**,
+ and **environmental factors**.
+
+ 📘 `Example `_
+ 🔗 `Documentation `_
+ 🧠 `Detailed theory `_
+
+6. **Point Clusterization**
+
+ A function for constructing **cluster polygons** based on a set of points using:
+
+ - Minimum **distance** between points.
+ - Minimum **number of points** in a cluster.
+
+ The function can also compute the **ratio of service types** in each cluster
+ for spatial analysis of service composition.
+
+ 📘 `Example `_
+ 🔗 `Documentation `_
+
+----
+
+City Graphs via *IduEdu*
+------------------------
+
+For optimal performance, **ObjectNat** is recommended to be used with graphs
+created by the `IduEdu `_ library.
+
+**IduEdu** is an open-source Python library designed for building and processing
+complex urban networks based on OpenStreetMap data.
+
+
+**IduEdu** can be installed via ``pip``::
+
+ pip install IduEdu
+
+Example usage::
+
+ from iduedu import get_4326_boundary, get_intermodal_graph
+
+ poly = get_4326_boundary(osm_id=1114252)
+ G_intermodal = get_intermodal_graph(territory=poly, clip_by_territory=True)
+
+----
+
+Installation
+------------
+
+**ObjectNat** can be installed via ``pip``::
+
+ pip install ObjectNat
+
+----
+
+Configuration
+-------------
+
+You can adjust logging and progress bar output using the config module::
+
+ from objectnat import config
+
+ config.change_logger_lvl("INFO") # mute debug logs
+ config.set_enable_tqdm(False) # disable tqdm progress bars
+
+----
+
+Contacts
+--------
+
+- `NCCR `_ — National Center for Cognitive Research
+- `IDU `_ — Institute of Design and Urban Studies
+- `Natalya Chichkova `_ — Project Manager
+- `Danila Oleynikov (Donny) `_ — Lead Software Engineer
+
+----
+
+Publications
+------------
+
+Coming soon.
diff --git a/README_RU.rst b/README_RU.rst
new file mode 100644
index 0000000..b7b4a32
--- /dev/null
+++ b/README_RU.rst
@@ -0,0 +1,173 @@
+ObjectNat
+=========
+
+Object-oriented Network Analysis Tools
+--------------------------------------
+
+.. |badge-black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
+ :target: https://github.com/psf/black
+ :alt: Стиль кода: black
+
+.. |badge-pypi| image:: https://img.shields.io/pypi/v/objectnat.svg
+ :target: https://pypi.org/project/objectnat/
+ :alt: Версия PyPI
+
+.. |badge-ci| image:: https://github.com/DDonnyy/ObjectNat/actions/workflows/ci_pipeline.yml/badge.svg
+ :target: https://github.com/DDonnyy/ObjectNat/actions/workflows/ci_pipeline.yml
+ :alt: CI статус
+
+.. |badge-codecov| image:: https://codecov.io/gh/DDonnyy/ObjectNat/graph/badge.svg?token=K6JFSJ02GU
+ :target: https://codecov.io/gh/DDonnyy/ObjectNat
+ :alt: Покрытие тестами
+
+.. |badge-license| image:: https://img.shields.io/badge/license-BSD--3--Clause-blue.svg
+ :target: https://opensource.org/licenses/BSD-3-Clause
+ :alt: Лицензия
+
+|badge-black| |badge-pypi| |badge-ci| |badge-codecov| |badge-license|
+
+`README (English) `_
+
+.. raw:: html
+
+
+
+
+
+----
+
+**ObjectNat** — это библиотека с открытым исходным кодом, разработанная командой **IDU**
+для пространственного и сетевого анализа в городских исследованиях.
+Библиотека предоставляет инструменты для анализа **доступности**, **видимости**,
+**распространения шума** и **обеспеченности сервисами**.
+
+----
+
+Основные функции
+----------------
+
+Каждая функция сопровождается **примером в Jupyter Notebook** и **документацией**.
+
+1. **Изохроны и транспортная доступность**
+
+ Изохроны представляют собой области, достижимые из исходной точки за заданное время по транспортной сети.
+ Эта функция позволяет анализировать транспортную доступность с использованием графов пешеходного, автомобильного,
+ общественного транспорта или их комбинации.
+
+ Библиотека поддерживает несколько методов построения изохрон:
+
+ - **Базовые изохроны**: отображают одну зону, достижимую за заданное время.
+ - **Шаговые изохроны**: делят зону доступности на интервалы времени (например, 3, 5, 10 минут).
+
+ 📘 `Пример `_
+ 🔗 `Документация `_
+
+2. **Зоны покрытия**
+
+ Функция генерации **зон покрытия** от набора исходных точек с использованием транспортной сети. Вычисляет область,
+ достижимую из каждой точки по **времени в пути** или **дистанции**, затем строит полигоны с помощью
+ **диаграмм Вороного** и обрезает их по заданной границе, если она указана.
+
+ 📘 `Пример `_
+ 🔗 `Документация `_
+
+3. **Анализ обеспеченности сервисами**
+
+ Функция оценки обеспеченности жилых зданий и их населения услугами (например, школы, поликлиники),
+ которые имеют ограниченную **вместимость** и заданный **порог доступности** (в минутах или метрах).
+ Функция моделирует **баланс спроса и предложения**, оценивая, насколько хорошо услуги удовлетворяют потребности
+ близлежащих зданий в пределах допустимого времени.
+
+ 📘 `Пример `_
+ 🔗 `Документация `_
+
+4. **Анализ видимости**
+
+ Функция оценки видимости от заданной точки или множества точек до близлежащих зданий в пределах заданного радиуса.
+ Применяется для оценки визуальной доступности в городской среде. Также реализован модуль для расчёта **зоны охвата**
+ по видимости с использованием плотной сетки наблюдателей (рекомендуется ~1000 точек с шагом 10–20 метров).
+ Точки можно сгенерировать по транспортной сети и распределить по её рёбрам.
+
+ 📘 `Пример `_
+ 🔗 `Документация `_
+
+5. **Моделирование шума**
+
+ Симуляция распространения шума от источников с учётом **препятствий**, **растительности** и **факторов окружающей среды**.
+
+ 📘 `Пример `_
+ 🔗 `Документация `_
+ 🧠 `Подробное описание `_
+
+6. **Кластеризация точек**
+
+ Функция построения **кластерных полигонов** по множеству точек на основе:
+
+ - Минимального **расстояния** между точками.
+ - Минимального **числа точек** в кластере.
+
+ Также функция может рассчитывать **соотношение типов услуг** в каждом кластере для пространственного анализа состава услуг.
+
+ 📘 `Пример `_
+ 🔗 `Документация `_
+
+----
+
+Городские графы с помощью *IduEdu*
+----------------------------------
+
+Для оптимальной работы **ObjectNat** рекомендуется использовать графы,
+созданные библиотекой `IduEdu `_.
+
+**IduEdu** — это библиотека на Python с открытым исходным кодом, предназначенная для построения и обработки
+сложных городских сетей на основе данных OpenStreetMap.
+
+
+**IduEdu** можно установить с помощью ``pip``::
+
+ pip install IduEdu
+
+Пример использования::
+
+ from iduedu import get_4326_boundary, get_intermodal_graph
+
+ poly = get_4326_boundary(osm_id=1114252)
+ G_intermodal = get_intermodal_graph(territory=poly, clip_by_territory=True)
+
+----
+
+Установка
+---------
+
+**ObjectNat** можно установить с помощью ``pip``::
+
+ pip install ObjectNat
+
+----
+
+Конфигурация
+------------
+
+Настройте вывод логов и прогресс-бары через модуль конфигурации::
+
+ from objectnat import config
+
+ config.change_logger_lvl("INFO") # отключить отладочные логи
+ config.set_enable_tqdm(False) # отключить прогресс-бары tqdm
+
+----
+
+Контакты
+--------
+
+- `НЦКР `_ — Национальный центр когнитивных исследований
+- `ИДУ `_ — Институт дизайна и урбанистики
+- `Наталья Чичкова `_ — менеджер проекта
+- `Данила Олейников (Donny) `_ — ведущий инженер-разработчик
+
+----
+
+Публикации
+----------
+
+Скоро будут опубликованы.
diff --git a/README_ru.md b/README_ru.md
deleted file mode 100644
index 28b8b22..0000000
--- a/README_ru.md
+++ /dev/null
@@ -1,108 +0,0 @@
-# ObjectNat
-
-[](https://github.com/psf/black)
-[](https://pypi.org/project/objectnat/)
-[](https://github.com/DDonnyy/ObjecNat/actions/workflows/ci_pipeline.yml)
-[](https://codecov.io/gh/DDonnyy/ObjectNat)
-[](https://opensource.org/licenses/MIT)
-
-
-
-
-
-#### **ObjectNat** — это библиотека с открытым исходным кодом, разработанная командой **IDU** для пространственного анализа.
-
-## Функции и как использовать
-
-1. **[Изохроны и транспортная доступность](./examples/isochrone_generator.ipynb)** — Изохроны представляют собой области,
-достижимые из исходной точки за заданное время по транспортной сети.
-Эта функция позволяет анализировать транспортную доступность с использованием графов пешеходного, автомобильного,
-общественного транспорта или их комбинации.
-
- Библиотека поддерживает несколько методов построения изохрон:
- - **Базовые изохроны**: отображают одну зону, достижимую за заданное время.
- - **Шаговые изохроны**: делят зону доступности на интервалы времени (например, 3, 5, 10 минут).
-
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/isochrones.html)
-
-2. **[Зоны покрытия](./examples/graph_coverage.ipynb)** — Функция генерации **зон покрытия** от набора исходных точек
-с использованием транспортной сети. Вычисляет область, достижимую из каждой точки по **времени в пути** или **дистанции**,
-затем строит полигоны с помощью **диаграмм Вороного** и обрезает их по заданной границе, если она указана.
-
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/coverage.html)
-
-3. **[Анализ обеспеченности сервисами](./examples/calculate_provision.ipynb)** — Функция оценки обеспеченности жилых зданий
-и их населения услугами (например, школы, поликлиники), которые имеют ограниченную **вместимость**
-и заданный **порог доступности** (в минутах или метрах). Функция моделирует **баланс спроса и предложения**,
-оценивая, насколько хорошо услуги удовлетворяют потребности близлежащих зданий в пределах допустимого времени.
-
- Библиотека также поддерживает:
- - **Перерасчёт** текущих результатов при изменении порога времени.
- - **Обрезку** результатов анализа по заданной зоне (например, границе района).
-
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/provision.html)
-
-4. **[Анализ видимости](./examples/visibility_analysis.ipynb)** — Функция оценки видимости от заданной точки или множества
-точек до близлежащих зданий в пределах заданного радиуса. Применяется для оценки визуальной доступности в городской среде.
-Также реализован модуль для расчёта **зоны охвата** по видимости с использованием плотной сетки наблюдателей (рекомендуется ~1000 точек с шагом 10–20 метров).
-Точки можно сгенерировать по транспортной сети и распределить по её рёбрам.
-
- Модуль включает:
- - **Быстрый приближённый метод** для больших объёмов данных.
- - **Точный метод** для локального детального анализа.
-
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/visibility.html)
-
-5. **[Моделирование шума](./examples/noise_simulation.ipynb)** — Симуляция распространения шума от источников с учётом **препятствий**,
-**растительности** и **факторов окружающей среды**.
-
- 🔗 **[Подробное описание в Wiki](https://github.com/DDonnyy/ObjectNat/wiki/Симуляция-шумового-распространения)**
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/noise.html)
-
-6. **[Кластеризация точек](./examples/point_clusterization.ipynb)** — Функция построения **кластерных полигонов** по множеству точек на основе:
- - Минимального **расстояния** между точками.
- - Минимального **числа точек** в кластере.
-
- Также функция может рассчитывать **соотношение типов услуг** в каждом кластере для пространственного анализа состава услуг.
-
- 📄 [See documentation](https://iduclub.github.io/ObjectNat/latest/usage/clustering.html)
-
-
-
-## Городские графы
-
-Для достижения оптимальной производительности функций пространственного анализа ObjectNat рекомендуется использовать городские графы,
-полученные с помощью библиотеки [IduEdu](https://github.com/DDonnyy/IduEdu).
-**IduEdu** — это библиотека на Python с открытым исходным кодом, предназначенная для построения и обработки
-сложных городских сетей на основе данных OpenStreetMap.
-
-**IduEdu** можно установить с помощью ``pip``:
-```
-pip install IduEdu
-```
-
-## Установка
-
-**ObjectNat** можно установить с помощью ``pip``:
-
-```
-pip install ObjectNat
-```
-
-### Изменения конфигурации
-
-```python
-from objectnat import config
-
-config.change_logger_lvl('INFO') # Чтобы отключить отладочные сообщения
-config.set_enable_tqdm(False) # Чтобы отключить прогресс-бары tqdm
-```
-
-## Контакты
-
-- [НЦКР](https://actcognitive.org/) — Национальный центр когнитивных разработок
-- [ИДУ](https://idu.itmo.ru/) — Институт дизайна и урбанистики
-- [Наталья Чичкова](https://t.me/nancy_nat) — менеджер проекта
-- [Данила Олейников (Donny)](https://t.me/ddonny_dd) — ведущий инженер-разработчик
-
-## Публикации
diff --git a/docs/_static/ONFavicon.svg b/docs/_static/ONFavicon.svg
new file mode 100644
index 0000000..180565f
--- /dev/null
+++ b/docs/_static/ONFavicon.svg
@@ -0,0 +1,99 @@
+
+
+
diff --git a/docs/_static/ONlogo.svg b/docs/_static/ONlogo.svg
new file mode 100644
index 0000000..ccd3887
--- /dev/null
+++ b/docs/_static/ONlogo.svg
@@ -0,0 +1,88 @@
+
+
+
diff --git a/docs/api.md b/docs/api.md
deleted file mode 100644
index e517cdb..0000000
--- a/docs/api.md
+++ /dev/null
@@ -1,5 +0,0 @@
-::: objectnat
- options:
- show_source: true
- show_root_heading: true
- show_signature_annotations: true
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..0f6c2b5
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,80 @@
+import os
+import sys
+from datetime import datetime
+from importlib.metadata import PackageNotFoundError
+from importlib.metadata import version as pkg_version
+
+from pygments.lexers import get_lexer_by_name
+from sphinx.highlighting import lexers
+
+sys.path.insert(0, os.path.abspath("../src"))
+
+project = "ObjectNat"
+author = "Donny"
+copyright = f"{datetime.now():%Y}, {author}"
+
+try:
+ release = pkg_version("objectnat")
+except PackageNotFoundError:
+ release = "0.0.0"
+
+version = ".".join(release.split(".")[:2])
+
+
+extensions = [
+ "myst_nb",
+ "sphinx.ext.autodoc",
+ "sphinx.ext.autosummary",
+ "sphinx.ext.napoleon",
+ "sphinx.ext.viewcode",
+ "sphinx.ext.intersphinx",
+ "sphinx_copybutton",
+ "sphinx_autodoc_typehints",
+ "sphinx_design",
+]
+
+html_theme = "furo"
+html_static_path = ["_static"]
+
+html_show_sourcelink = True
+
+html_logo = "_static/ONlogo.svg"
+html_favicon = "_static/ONFavicon.svg"
+
+myst_enable_extensions = ["colon_fence", "deflist", "substitution", "linkify", "attrs_block", "attrs_inline"]
+nb_execution_mode = "off"
+nb_execution_timeout = 600
+nb_execution_raise_on_error = False
+nb_render_image_options = {"align": "center"}
+
+autosummary_generate = True
+autodoc_typehints = "description"
+autodoc_member_order = "bysource"
+
+
+intersphinx_mapping = {
+ "python": ("https://docs.python.org/3", None),
+ "numpy": ("https://numpy.org/doc/stable/", None),
+ "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None),
+ "geopandas": ("https://geopandas.org/en/stable/", None),
+ "networkx": ("https://networkx.org/documentation/stable/", None),
+ "shapely": ("https://shapely.readthedocs.io/en/stable/", None),
+}
+
+
+napoleon_google_docstring = True
+napoleon_numpy_docstring = True
+napoleon_preprocess_types = True
+
+napoleon_type_aliases = {
+ "gpd.GeoDataFrame": "geopandas.GeoDataFrame",
+ "GeoDataFrame": "geopandas.GeoDataFrame",
+ "nx.Graph": "networkx.Graph",
+ "Graph": "networkx.Graph",
+ "Series": "pandas.Series",
+ "DataFrame": "pandas.DataFrame",
+ "LineString": "shapely.geometry.LineString",
+}
+
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
+lexers["ipython2"] = get_lexer_by_name("ipython3")
diff --git a/examples/examples_data/buildings.parquet b/docs/examples/examples_data/buildings.parquet
similarity index 100%
rename from examples/examples_data/buildings.parquet
rename to docs/examples/examples_data/buildings.parquet
diff --git a/examples/examples_data/matrix_time.parquet b/docs/examples/examples_data/matrix_time.parquet
similarity index 100%
rename from examples/examples_data/matrix_time.parquet
rename to docs/examples/examples_data/matrix_time.parquet
diff --git a/examples/examples_data/services.parquet b/docs/examples/examples_data/services.parquet
similarity index 100%
rename from examples/examples_data/services.parquet
rename to docs/examples/examples_data/services.parquet
diff --git a/examples/examples_data/trees.parquet b/docs/examples/examples_data/trees.parquet
similarity index 100%
rename from examples/examples_data/trees.parquet
rename to docs/examples/examples_data/trees.parquet
diff --git a/docs/index.md b/docs/index.md
deleted file mode 100644
index 140728b..0000000
--- a/docs/index.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# ObjectNat
-
-[](https://github.com/psf/black)
-[](https://pypi.org/project/objectnat/)
-[](https://github.com/DDonnyy/ObjecNat/actions/workflows/ci_pipeline.yml)
-[](https://codecov.io/gh/DDonnyy/ObjectNat)
-[](https://opensource.org/licenses/MIT)
-
-
-
-
-
-**ObjectNat** is an open-source library created for geospatial analysis created by **IDU team**
-
-## Contacts
-
-- [NCCR](https://actcognitive.org/) - National Center for Cognitive Research
-- [IDU](https://idu.itmo.ru/) - Institute of Design and Urban Studies
-- [Natalya Chichkova](https://t.me/nancy_nat) - project manager
-- [Danila Oleynikov (Donny)](https://t.me/ddonny_dd) - lead software engineer
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..b10b229
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,163 @@
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ methods/isochrones
+ methods/coverage
+ methods/provision
+ methods/visibility
+ methods/noise
+ methods/clustering
+ methods/examples/index
+
+ObjectNat
+=========
+
+Object-oriented Network Analysis Tools
+--------------------------------------
+
+**ObjectNat** — an open-source Python library for **object-oriented network analysis** and **spatial accessibility modeling**,
+developed by the **IDU team** at ITMO University.
+
+
+|badge-black| |badge-pypi| |badge-ci| |badge-cov| |badge-license| |badge-github|
+
+.. |badge-black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
+ :target: https://github.com/psf/black
+ :alt: Code style: black
+
+.. |badge-pypi| image:: https://img.shields.io/pypi/v/objectnat.svg
+ :target: https://pypi.org/project/objectnat/
+ :alt: PyPI version
+
+.. |badge-ci| image:: https://github.com/IDUclub/ObjectNat/actions/workflows/ci_pipeline.yml/badge.svg
+ :target: https://github.com/IDUclub/ObjectNat/actions/workflows/ci_pipeline.yml
+ :alt: CI
+
+.. |badge-cov| image:: https://codecov.io/gh/DDonnyy/ObjectNat/graph/badge.svg?token=K6JFSJ02GU
+ :target: https://codecov.io/gh/DDonnyy/ObjectNat
+ :alt: Coverage
+
+.. |badge-license| image:: https://img.shields.io/badge/license-BSD--3--Clause-blue.svg
+ :target: https://opensource.org/licenses/BSD-3-Clause
+ :alt: License
+
+.. |badge-github| image:: https://img.shields.io/badge/GitHub-IDUclub%2FObjectNat-181717?logo=github
+ :target: https://github.com/IDUclub/ObjectNat
+ :alt: GitHub
+
+----
+
+Overview
+--------
+
+**ObjectNat** extends standard network analysis with a focus on **object-level geospatial computation**.
+It provides a unified set of tools for analyzing **coverage**, **provision**, **accessibility**,
+**visibility**, **noise simulation**, and **spatial clustering** — all based on graph connectivity.
+
+The library integrates seamlessly with:
+- **GeoPandas**, **Shapely**, and **NetworkX** for spatial operations;
+- **IduEdu** for graph preparation and multimodal routing;
+- Python's scientific ecosystem (NumPy, Pandas, Matplotlib, etc).
+
+----
+
+Features
+--------
+
+- **Isochrones & Accessibility**
+
+ - :func:`objectnat.get_accessibility_isochrones`, :func:`objectnat.get_accessibility_isochrone_stepped`
+- **Coverage Zones**
+
+ - :func:`objectnat.get_graph_coverage`, :func:`objectnat.get_radius_coverage`, :func:`objectnat.get_stepped_graph_coverage`
+- **Service Provision**
+
+ - :func:`objectnat.get_service_provision` , :func:`objectnat.recalculate_links`, :func:`objectnat.clip_provision`
+- **Noise Simulation**
+
+ - :func:`objectnat.simulate_noise`, :func:`objectnat.calculate_simplified_noise_frame`
+- **Visibility Analysis**
+
+ - :func:`objectnat.get_visibility_accurate`, :func:`objectnat.get_visibility`, :func:`objectnat.get_visibilities_from_points`
+- **Clustering**
+
+ - :func:`objectnat.get_clusters_polygon`
+- **Utilities**
+
+ - Graph and geometry helpers: `geom_utils`, `graph_utils`, `math_utils`
+
+----
+
+Installation
+------------
+
+```
+pip install objectnat
+```
+
+- > Requires Python 3.11+ and the standard geospatial stack
+- > (Pandas, GeoPandas, Shapely, NetworkX, NumPy).
+
+----
+
+Quickstart
+----------
+
+To ensure optimal performance of ObjectNat's geospatial analysis functions, it's recommended
+to utilize urban graphs sourced from the `IduEdu `_ library.
+**IduEdu** is an open-source Python library designed for the creation and manipulation of complex
+city networks derived from OpenStreetMap data.
+
+.. code-block:: python
+
+ # Install required packages (uncomment if needed)
+ # !pip install iduedu objectnat
+
+ from iduedu import get_4326_boundary, get_intermodal_graph
+ from objectnat import get_accessibility_isochrones
+
+ # Load boundary and build graph for a region (OSM ID 1114252)
+ poly = get_4326_boundary(osm_id=1114252)
+ G = get_intermodal_graph(territory=poly, clip_by_territory=True)
+
+ # Compute accessibility isochrones from several points
+ stepped_isochrone, pt_stops, pt_routes = get_accessibility_isochrone_stepped(
+ isochrone_type='separate',
+ point=point,
+ weight_type="time_min",
+ weight_value=10,
+ nx_graph=G_intermodal,
+ step=2
+ )
+
+ stepped_isochrone.explore()
+
+----
+
+> Contributions are very welcome!
+> Open an issue or PR on GitHub to suggest new features or improvements.
+
+----
+
+Contacts
+--------
+
+- `NCCR `_ — National Center for Cognitive Research
+- `IDU `_ — Institute of Design and Urban Studies
+- `Natalya Chichkova `_ — Project Manager
+- `Danila Oleynikov (Donny) `_ — Lead Software Engineer
+
+----
+
+License
+-------
+
+This project is open-source. See the :file:`LICENSE.txt` file for details.
+
+----
+
+Publications
+------------
+
+Coming soon…
diff --git a/docs/usage/clustering.md b/docs/methods/clustering.rst
similarity index 51%
rename from docs/usage/clustering.md
rename to docs/methods/clustering.rst
index b1abb8c..4ea2959 100644
--- a/docs/usage/clustering.md
+++ b/docs/methods/clustering.rst
@@ -1,23 +1,30 @@
-# **Point Clusterization**
+Point Clusterization
+====================
Clusterization groups nearby points into polygons based on spatial proximity and minimum cluster size.
It can be used for identifying dense urban areas, service hubs, or catchment zones.
----
+----
-## **Cluster Generation**
+**Cluster Generation**
+~~~~~~~~~~~~~~~~~~~~~~
Clusters are generated using spatial rules:
- **Minimum distance** between points to be included in the same cluster.
- **Minimum number of points** required to form a valid cluster.
-::: objectnat.get_clusters_polygon
- options:
- show_root_heading: true
- heading_level: None
+.. currentmodule:: objectnat
-
+.. autofunction:: get_clusters_polygon
----
+.. image:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/building_clusters.png
+ :alt: building_clusters
+ :align: center
+----
+
+Example notebook
+----------------
+
+:doc:`examples/clustering`
\ No newline at end of file
diff --git a/docs/methods/coverage.rst b/docs/methods/coverage.rst
new file mode 100644
index 0000000..2af712a
--- /dev/null
+++ b/docs/methods/coverage.rst
@@ -0,0 +1,100 @@
+Graph Coverage Zones from Points
+================================
+
+Coverage zones represent areas that can be reached from multiple source points
+within a certain **time** or **distance** limit using a transport network.
+They are built by calculating reachability per point, generating **Voronoi polygons**,
+and optionally clipping them to a defined boundary.
+
+----
+
+ The library supports several methods for generating coverage zones,
+ depending on whether you use a full transport graph or simplified geometric rules.
+
+----
+
+Coverage Using Transport Graph
+------------------------------
+
+Uses a full **routing engine** to determine reachable areas per point,
+then builds coverage zones based on actual network paths.
+
+.. autofunction:: objectnat.get_graph_coverage
+
+----
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/coverage_zones_time_10min.png
+ :alt: coverage_zones_time_10min
+ :align: center
+ :width: 80%
+
+ Coverage zones generated by **travel time (10 minutes)** on a transport graph.
+
+----
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/coverage_zones_distance_600m.png
+ :alt: coverage_zones_distance_600m
+ :align: center
+ :width: 80%
+
+ Coverage zones generated by **distance (600 meters)** on a transport graph.
+
+----
+
+Coverage Using Radius Only
+--------------------------
+
+Generates fixed **radius-based buffers** per point without routing,
+then merges or clips them via **Voronoi** diagrams for cleaner borders.
+
+.. autofunction:: objectnat.get_radius_coverage
+
+----
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/coverage_zones_radius_distance_800m.png
+ :alt: coverage_zones_distance_radius_voronoi
+ :align: center
+ :width: 80%
+
+ Radius-based coverage zones (800 meters) with Voronoi clipping.
+
+----
+
+Stepped Graph Coverage
+----------------------
+
+Creates **multi-step coverage zones** (e.g., 5, 10, 15 minutes)
+using the full transport graph for each source point.
+
+.. autofunction:: objectnat.get_stepped_graph_coverage
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/stepped_coverage_zones_separate.png
+ :alt: stepped_coverage_zones_separate
+ :align: center
+ :width: 80%
+
+ Stepped coverage zones displayed as **separate intervals**.
+
+----
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/stepped_coverage_zones_voronoi.png
+ :alt: stepped_coverage_zones_voronoi
+ :align: center
+ :width: 80%
+
+ Stepped coverage zones merged using **Voronoi partitioning**.
+
+----
+
+.. note::
+
+ Coverage zones are a powerful tool for evaluating **service accessibility**,
+ **network efficiency**, and **urban reachability**.
+
+----
+
+Example notebook
+----------------
+
+:doc:`examples/coverage`
+
diff --git a/examples/calculate_adjacency_matrix.ipynb b/docs/methods/examples/calculate_adjacency_matrix.ipynb
similarity index 91%
rename from examples/calculate_adjacency_matrix.ipynb
rename to docs/methods/examples/calculate_adjacency_matrix.ipynb
index 6d15a2b..405ac5b 100644
--- a/examples/calculate_adjacency_matrix.ipynb
+++ b/docs/methods/examples/calculate_adjacency_matrix.ipynb
@@ -4,7 +4,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "## Building-to-Service Travel Time Matrix with Intermodal Graph\n",
+ "# Building-to-Service Travel Time Matrix with Intermodal Graph\n",
"This notebook demonstrates how to compute a time-based adjacency matrix between two GeoDataFrames\n",
"(e.g., buildings and services) using a multimodal transport graph.\n",
"\n",
@@ -46,7 +46,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 1. Load Input Geospatial Data\n",
+ "## 1. Load Input Geospatial Data\n",
"Load the GeoDataFrames of buildings (origins) and services (destinations).\n"
],
"id": "68af599b21a7895d"
@@ -67,7 +67,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 2. Create Coverage Polygon for Graph Download\n",
+ "## 2. Create Coverage Polygon for Graph Download\n",
"Compute a polygon that encompasses both datasets to define the spatial extent for graph download.\n",
"This is done by computing a convex hull over all geometries and buffering it slightly.\n"
],
@@ -89,7 +89,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 3. Download and Clip Intermodal Graph\n",
+ "## 3. Download and Clip Intermodal Graph\n",
"Download the intermodal (multi-modal) network graph using the defined polygon.\n",
"This includes walking paths and public transport networks."
],
@@ -100,7 +100,7 @@
"cell_type": "code",
"source": [
"# Load multimodal graph clipped to polygon\n",
- "G_intermodal = get_intermodal_graph(polygon=polygon, clip_by_bounds=True)"
+ "G_intermodal = get_intermodal_graph(territory=polygon, clip_by_territory=True)"
],
"id": "1e643d3fdc052876",
"outputs": [],
@@ -110,7 +110,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 4. Compute Adjacency Matrix (Travel Time)\n",
+ "## 4. Compute Adjacency Matrix (Travel Time)\n",
"Calculate a travel-time-based adjacency matrix from buildings to services.\n",
"\n",
"Parameters:\n",
@@ -140,7 +140,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 5. Save Adjacency Matrix\n",
+ "## 5. Save Adjacency Matrix\n",
"Export the result for further processing, e.g., with `ObjectNat`'s service provision tools."
],
"id": "8c56b37f6c2f508f"
diff --git a/examples/point_clusterization.ipynb b/docs/methods/examples/clustering.ipynb
similarity index 94%
rename from examples/point_clusterization.ipynb
rename to docs/methods/examples/clustering.ipynb
index 46b658a..5580437 100644
--- a/examples/point_clusterization.ipynb
+++ b/docs/methods/examples/clustering.ipynb
@@ -4,7 +4,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "## Spatial Clustering of GeoDataFrame into Polygons\n",
+ "# Spatial Clustering of GeoDataFrame into Polygons\n",
"This example demonstrates how to cluster spatial point data (e.g., buildings or services) into polygons using density-based algorithms:\n",
"- DBSCAN or HDBSCAN methods\n",
"- Parameters for minimum distance and minimum points per cluster"
@@ -27,7 +27,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 1. Load Point Dataset\n",
+ "## 1. Load Point Dataset\n",
"Load a set of points (e.g., buildings) for spatial clustering.\n"
],
"id": "fb6c09592d642382"
@@ -47,7 +47,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- " ### 2. Perform Clustering and Create Cluster Polygons\n",
+ " ## 2. Perform Clustering and Create Cluster Polygons\n",
" Use the `get_clusters_polygon()` function to cluster points into groups based on spatial proximity.\n",
" \n",
" Parameters:\n",
diff --git a/examples/coverage_zones.ipynb b/docs/methods/examples/coverage.ipynb
similarity index 92%
rename from examples/coverage_zones.ipynb
rename to docs/methods/examples/coverage.ipynb
index 14bf966..3c1097a 100644
--- a/examples/coverage_zones.ipynb
+++ b/docs/methods/examples/coverage.ipynb
@@ -4,7 +4,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "## Graph Coverage Analysis for Service Points\n",
+ "# Graph Coverage Analysis for Service Points\n",
"\n",
"This notebook demonstrates how to calculate coverage zones from service points through a multimodal transportation network using Dijkstra's algorithm and Voronoi diagrams."
],
@@ -26,7 +26,7 @@
"cell_type": "code",
"source": [
"# Import dependencies\n",
- "from iduedu import get_intermodal_graph, get_boundary\n",
+ "from iduedu import get_intermodal_graph, get_4326_boundary\n",
"import geopandas as gpd\n",
"from objectnat import get_graph_coverage,get_stepped_graph_coverage,get_radius_coverage"
],
@@ -38,7 +38,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 1. Load Transportation Network\n",
+ "## 1. Load Transportation Network\n",
"First, we retrieve the multimodal graph (roads, public transport, etc.) for a specified region using its OSM ID."
],
"id": "5084078ebb6beef2"
@@ -51,8 +51,8 @@
},
"source": [
"# Get city boundary and transportation network\n",
- "poly = get_boundary(osm_id=1114252) # Example OSM ID for a city\n",
- "G_intermodal = get_intermodal_graph(polygon=poly, clip_by_bounds=True)"
+ "poly = get_4326_boundary(osm_id=1114252) # Example OSM ID for a city\n",
+ "G_intermodal = get_intermodal_graph(territory=poly, clip_by_territory=True)"
],
"outputs": [],
"execution_count": null
@@ -61,7 +61,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 2. Load Service Points\n",
+ "## 2. Load Service Points\n",
"These represent locations (e.g., healthcare facilities, schools) for which we want to calculate coverage zones."
],
"id": "18c5a199616284b0"
@@ -81,7 +81,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 3. Calculate Coverage by Distance\n",
+ "## 3. Calculate Coverage by Distance\n",
"Creates service areas based on maximum travel distance (800 meters in this example)."
],
"id": "9e3ebbd07107a149"
@@ -109,7 +109,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 4. Calculate Coverage by Travel Time\n",
+ "## 4. Calculate Coverage by Travel Time\n",
"Creates service areas based on maximum travel time (10 minutes in this example), clipped to the city boundary."
],
"id": "5f8d6888bdbf4716"
@@ -153,7 +153,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 5. Calculate stepped Coverage by Travel Time\n",
+ "## 5. Calculate stepped Coverage by Travel Time\n",
"This method divides the total travel time threshold into steps (e.g. every 2 minutes), creating incremental zones.\n",
"Useful for visualizing service accessibility gradients.\n",
"\n",
@@ -206,7 +206,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 6. Calculate Radius-Based Coverage\n",
+ "## 6. Calculate Radius-Based Coverage\n",
"If a transport network is unavailable or unnecessary, use simple circular buffers around service points.\n",
"\n",
"This method creates geometric buffers with specified radius (e.g., 500 meters)."
diff --git a/docs/methods/examples/index.rst b/docs/methods/examples/index.rst
new file mode 100644
index 0000000..11fa3b2
--- /dev/null
+++ b/docs/methods/examples/index.rst
@@ -0,0 +1,15 @@
+Examples
+========
+
+.. toctree::
+ :maxdepth: 2
+
+
+ isochrones
+ coverage
+ provision
+ visibility
+ noise
+ clustering
+ calculate_adjacency_matrix
+
diff --git a/examples/isochrone_generator.ipynb b/docs/methods/examples/isochrones.ipynb
similarity index 93%
rename from examples/isochrone_generator.ipynb
rename to docs/methods/examples/isochrones.ipynb
index 2136aa6..d9e9856 100644
--- a/examples/isochrone_generator.ipynb
+++ b/docs/methods/examples/isochrones.ipynb
@@ -4,7 +4,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "## Isochrone Analysis from Points of Interest\n",
+ "# Isochrone Analysis from Points of Interest\n",
"This notebook demonstrates how to generate accessibility isochrones from single or multiple points using different methods:\n",
"- Simple `radius` and `ways` isochrones\n",
"- Stepped isochrones with customizable intervals"
@@ -27,7 +27,7 @@
"cell_type": "code",
"source": [
"# Import necessary libraries\n",
- "from iduedu import get_intermodal_graph, get_boundary\n",
+ "from iduedu import get_intermodal_graph, get_4326_boundary\n",
"import geopandas as gpd\n",
"from shapely import Point\n",
"from objectnat import get_accessibility_isochrones, get_accessibility_isochrone_stepped"
@@ -40,7 +40,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 1. Load Intermodal Graph\n",
+ "## 1. Load Intermodal Graph\n",
"Load a multimodal transportation graph (roads, public transport, etc.) for a specific region using its OSM ID."
],
"id": "494425a561aa50ec"
@@ -49,8 +49,8 @@
"cell_type": "code",
"source": [
"# Load boundary and graph for a specific region using OSM ID 1114252.\n",
- "poly = get_boundary(osm_id=1114252)\n",
- "G_intermodal = get_intermodal_graph(polygon=poly, clip_by_bounds=True)"
+ "poly = get_4326_boundary(osm_id=1114252)\n",
+ "G_intermodal = get_intermodal_graph(territory=poly, clip_by_territory=True)"
],
"metadata": {
"collapsed": false
@@ -63,7 +63,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 2. Create Points of Interest\n",
+ "## 2. Create Points of Interest\n",
"Define one or more source points from which isochrones will be generated."
],
"id": "917bf19ff192faac"
@@ -83,7 +83,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 3. Generate Radius Isochrones\n",
+ "## 3. Generate Radius Isochrones\n",
"Create circular isochrones using a travel time threshold (e.g. 10 minutes)."
],
"id": "7127732b199acab6"
@@ -113,7 +113,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 4. Generate Ways Isochrones\n",
+ "## 4. Generate Ways Isochrones\n",
"Create road network-based polygons representing reachable areas within a time or distance threshold."
],
"id": "1e9a3026b7537291"
@@ -143,7 +143,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 5. Compare Isochrone Types\n",
+ "## 5. Compare Isochrone Types\n",
"Overlay both types of isochrones to compare coverage."
],
"id": "38499d16fdc1991e"
@@ -163,7 +163,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 6. Generate Stepped Isochrones (Radius)\n",
+ "## 6. Generate Stepped Isochrones (Radius)\n",
"Create concentric buffer zones with stepped intervals (e.g. every 3 minutes).\n"
],
"id": "739b0d17e9be6e02"
@@ -191,7 +191,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 7. Generate Stepped Isochrones (Ways)\n",
+ "## 7. Generate Stepped Isochrones (Ways)\n",
"Create layered polygons in the road network with custom intervals (e.g. every 3 minutes).\n"
],
"id": "5320bc04bdc43135"
@@ -218,7 +218,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 8. Generate Stepped Isochrones (Separate)\n",
+ "## 8. Generate Stepped Isochrones (Separate)\n",
"Create distinct buffer rings for each interval."
],
"id": "350e096ecc82ec2f"
@@ -258,7 +258,7 @@
{
"metadata": {},
"cell_type": "markdown",
- "source": "## Animation for stepped isochrones:",
+ "source": "## Animation for stepped isochrones",
"id": "dbdc88b0d14ec294"
},
{
diff --git a/examples/noise_simulation.ipynb b/docs/methods/examples/noise.ipynb
similarity index 97%
rename from examples/noise_simulation.ipynb
rename to docs/methods/examples/noise.ipynb
index 3c3eb07..9bc66d8 100644
--- a/examples/noise_simulation.ipynb
+++ b/docs/methods/examples/noise.ipynb
@@ -4,7 +4,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "## Noise Propagation Simulation\n",
+ "# Noise Propagation Simulation\n",
"This section demonstrates how to simulate the propagation of noise in an urban environment using a point source,\n",
"obstacles (e.g., buildings), and optional vegetation (e.g., trees). The `simulate_noise` function models the \n",
"attenuation of noise based on geometry, absorption, reflections, and environmental parameters.\n"
@@ -38,7 +38,7 @@
{
"metadata": {},
"cell_type": "markdown",
- "source": "### 1. Define Noise Source\n",
+ "source": "## 1. Define Noise Source\n",
"id": "d17c9f5c9d0a1e32"
},
{
@@ -59,7 +59,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 2. Load Obstacle and Tree Data\n",
+ "## 2. Load Obstacle and Tree Data\n",
"Load obstacle (building) and tree layers from local files, and project them to the same CRS used for simulation.\n"
],
"id": "2b92b561b2fc0613"
@@ -82,7 +82,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 3. Run Noise Simulation\n",
+ "## 3. Run Noise Simulation\n",
"Simulate the propagation of noise using a point source with specified parameters. The simulation accounts for:\n",
"- Obstacles and their absorption\n",
"- Tree-based scattering\n",
@@ -120,7 +120,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 4. Visualize the Result\n",
+ "## 4. Visualize the Result\n",
"Visualize the noise propagation result on a map using a color scale that reflects noise levels (in dB).\n"
],
"id": "7b5484096b6d206d"
@@ -140,7 +140,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 5. Create a Simplified Noise Frame (No Full Simulation)\n",
+ "## 5. Create a Simplified Noise Frame (No Full Simulation)\n",
"\n",
"This section builds a simplified noise exposure map (noise \"frame\") across a territory using only geometric\n",
"visibility and sound decay, without performing full wave-based simulation.\n",
@@ -224,7 +224,7 @@
{
"metadata": {},
"cell_type": "markdown",
- "source": "### Section for GIF creation",
+ "source": "## Section for GIF creation",
"id": "31cb77ec9dc93fc3"
},
{
diff --git a/examples/calculate_provision.ipynb b/docs/methods/examples/provision.ipynb
similarity index 95%
rename from examples/calculate_provision.ipynb
rename to docs/methods/examples/provision.ipynb
index 182d7f7..0ae5eb4 100644
--- a/examples/calculate_provision.ipynb
+++ b/docs/methods/examples/provision.ipynb
@@ -4,7 +4,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "## Service Provision Analysis\n",
+ "# Service Provision Analysis\n",
"This notebook demonstrates how to analyze service accessibility from buildings using precomputed distances:\n",
"- Compute basic service provision\n",
"- Adjust provision thresholds\n",
@@ -29,7 +29,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 1. Load Input Data\n",
+ "## 1. Load Input Data\n",
"Load buildings, services, and an adjacency matrix of distances or travel times between them. All layers are reprojected to UTM (EPSG:32636) for consistency.\n"
],
"id": "133bb319e2fd5ec3"
@@ -51,7 +51,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 2. Compute Initial Service Provision\n",
+ "## 2. Compute Initial Service Provision\n",
"Compute how well buildings are served by nearby services using the `get_service_provision()` function.\n",
"The `threshold` parameter defines the maximum distance or time for service availability."
],
@@ -78,7 +78,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 3. Visualize Service Provision\n",
+ "## 3. Visualize Service Provision\n",
"Use an interactive map to inspect which buildings are well-served and which are underserved.\n"
],
"id": "f267ccc667dea286"
@@ -104,7 +104,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 4. Recalculate Provision with New Threshold\n",
+ "## 4. Recalculate Provision with New Threshold\n",
"Update the service provision based on a new threshold (e.g., longer acceptable walking or travel time).\n"
],
"id": "9f941a72e57af722"
@@ -139,7 +139,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 5. Clip Provision to a Subarea\n",
+ "## 5. Clip Provision to a Subarea\n",
"Limit the analysis to a specific geographic region using any interested area.\n"
],
"id": "4d8eaec54833393"
diff --git a/examples/visibility_analysis.ipynb b/docs/methods/examples/visibility.ipynb
similarity index 83%
rename from examples/visibility_analysis.ipynb
rename to docs/methods/examples/visibility.ipynb
index 916eab4..5c99c0e 100644
--- a/examples/visibility_analysis.ipynb
+++ b/docs/methods/examples/visibility.ipynb
@@ -4,7 +4,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "## Line-of-Sight Visibility Analysis\n",
+ "# Line-of-Sight Visibility Analysis\n",
"This notebook demonstrates how to compute visible areas from a viewpoint or multiple points using:\n",
"- Fast approximate visibility (suitable for quick overviews)\n",
"- Accurate visibility analysis (respecting occlusions)\n",
@@ -17,7 +17,7 @@
"cell_type": "code",
"source": [
"# Import necessary libraries\n",
- "from objectnat import get_visibility, get_visibility_accurate, get_visibilities_from_points\n",
+ "from objectnat import get_visibility, get_visibility_accurate\n",
"import geopandas as gpd\n",
"from shapely.geometry import Point"
],
@@ -29,7 +29,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 1. Load Obstacle Data\n",
+ "## 1. Load Obstacle Data\n",
"Load a building layer representing line-of-sight obstacles. This dataset is used to compute occlusions in the urban environment.\n"
],
"id": "1afa4218134b2c84"
@@ -49,7 +49,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 2. Define Viewpoint\n",
+ "## 2. Define Viewpoint\n",
"Specify the observation point from which visibility will be computed. Coordinates must match the CRS of the obstacles dataset.\n"
],
"id": "c7d345277339355a"
@@ -59,7 +59,8 @@
"cell_type": "code",
"source": [
"# Define a single viewpoint in WGS 84\n",
- "point_from = gpd.GeoDataFrame(geometry=[Point(30.2312112, 59.9482336)], crs=4326)"
+ "point_from = gpd.GeoDataFrame(geometry=[Point(30.2312112, 59.9482336)], crs=4326)\n",
+ "radius = 500"
],
"id": "784128c4f7c5fe89",
"outputs": [],
@@ -69,7 +70,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 3. Fast Visibility Calculation\n",
+ "## 3. Fast Visibility Calculation\n",
"Compute visibility using a fast, approximate method. This is suitable for real-time feedback or exploratory analysis.\n",
"**Note:** May produce artifacts (e.g., visibility behind walls).\n"
],
@@ -80,7 +81,7 @@
"cell_type": "code",
"source": [
"# Fast visibility (less accurate)\n",
- "result_fast = get_visibility(point_from, obstacles, view_distance=500)\n",
+ "result_fast = get_visibility(point_from, obstacles, view_distance=radius)\n",
"# Computes visibility polygon from the viewpoint with a 500-meter radius using low-resolution simulation."
],
"id": "8797859dfe469ace",
@@ -91,7 +92,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 4. Accurate Visibility Calculation\n",
+ "## 4. Accurate Visibility Calculation\n",
"Use the more precise `get_visibility_accurate()` function, which simulates occlusion and limited sightlines.\n",
"This method is slower but produces more reliable results.\n"
],
@@ -102,7 +103,7 @@
"cell_type": "code",
"source": [
"# Accurate visibility (includes occlusion and bottleneck modeling)\n",
- "result_accurate = get_visibility_accurate(point_from, obstacles, view_distance=500)\n",
+ "result_accurate = get_visibility_accurate(point_from, obstacles, view_distance=radius)\n",
"# Simulates realistic visibility by tracing around buildings and respecting occlusions."
],
"id": "4c08935e3e1bf3ca",
@@ -113,8 +114,8 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 5. Visualization\n",
- "Visualize obstacles and both visibility methods on an interactive map using GeoPandas.\n"
+ "## 5. Visualization\n",
+ "Visualize obstacles and both visibility methods\n"
],
"id": "e1fdf25b75fbe716"
},
@@ -122,14 +123,24 @@
"metadata": {},
"cell_type": "code",
"source": [
- "# Accurate visibility polygon in green\n",
- "m = result_accurate.explore( color='Green', tiles='CartoDB positron')\n",
- "# Add buildings\n",
- "obstacles.explore(m=m,color='lightgray')\n",
- "# Add fast visibility polygon in red\n",
- "result_fast.explore(m=m, color='red')\n",
- "# Add viewpoint in purple\n",
- "point_from.explore(m=m, color='purple')"
+ "from shapely import Point\n",
+ "\n",
+ "from shapely import Point\n",
+ "\n",
+ "# Red area = False Positive (Simple method only)\n",
+ "simple_only = gpd.overlay(result_fast, result_accurate, how=\"difference\")\n",
+ "\n",
+ "# Green area = Advantage (Accurate method only)\n",
+ "accurate_only = gpd.overlay(result_accurate, result_fast, how=\"difference\")\n",
+ "\n",
+ "# Blue area = Agreement Area (both methods overlap)\n",
+ "common_area = gpd.overlay(result_fast, result_accurate, how=\"intersection\")\n",
+ "\n",
+ "# Light gray = Obstacles (context layer)\n",
+ "m = common_area.explore(color='blue', tiles='CartoDB positron')\n",
+ "obstacles.explore(m=m, color='lightgray')\n",
+ "simple_only.explore(m=m, color='red')\n",
+ "accurate_only.explore(m=m, color='green')\n"
],
"id": "26c72acea424b17",
"outputs": [],
@@ -139,7 +150,7 @@
"metadata": {},
"cell_type": "markdown",
"source": [
- "### 6. Visibility from Multiple Viewpoints (Parallelized)\n",
+ "## 6. Visibility from Multiple Viewpoints (Parallelized)\n",
"For batch visibility simulation, use `get_visibilities_from_points()` with multiple locations.\n",
"The computation is performed in parallel using multiprocessing."
],
@@ -173,9 +184,7 @@
{
"metadata": {},
"cell_type": "markdown",
- "source": [
- "## Calculate visibility catchment area (multiproseccing)"
- ],
+ "source": "## Calculate visibility catchment area (multiprocessing)",
"id": "f9aff770aa8f63bb"
},
{
diff --git a/docs/methods/isochrones.rst b/docs/methods/isochrones.rst
new file mode 100644
index 0000000..69e4a1e
--- /dev/null
+++ b/docs/methods/isochrones.rst
@@ -0,0 +1,87 @@
+Isochrones and Transport Accessibility
+======================================
+
+Isochrones represent areas reachable from a starting point within a given time limit
+along a transport network.
+This functionality enables analysis of transport accessibility using **pedestrian**, **automobile**, **public transport** graphs, or their combination.
+
+----
+
+ The library provides several methods for generating isochrones depending on the required level of detail and visualization.
+
+----
+
+Baseline Isochrones
+-------------------
+
+Show a single area reachable within a specified time.
+
+.. autofunction:: objectnat.get_accessibility_isochrones
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/isochrone_ways_15_min.png
+ :alt: isochrone_ways_15_min
+ :align: center
+ :width: 80%
+
+ Isochrone for **road network** within 15 minutes.
+
+----
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/isochrone_radius_15_min.png
+ :alt: isochrone_radius_15_min
+ :align: center
+ :width: 80%
+
+ Isochrone using **radius-based** method (15 min).
+
+----
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/isochrone_3points_radius_8_min.png
+ :alt: isochrone_3points_radius_8_min
+ :align: center
+ :width: 80%
+
+ Isochrones for **three start points** (8 min).
+
+----
+
+Stepped Isochrones
+------------------
+
+Show accessibility ranges divided into time intervals (e.g., 5, 10, 15 minutes).
+
+.. autofunction:: objectnat.get_accessibility_isochrone_stepped
+
+----
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/stepped_isochrone_ways_15_min.png
+ :alt: stepped_isochrone_ways_15_min
+ :align: center
+ :width: 80%
+
+ Stepped isochrones for **road network** (5–15 min).
+
+----
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/stepped_isochrone_radius_15_min.png
+ :alt: stepped_isochrone_radius_15_min
+ :align: center
+ :width: 80%
+
+ Stepped **radius-based** isochrones (5–15 min).
+
+----
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/stepped_isochrone_separate_15_min.png
+ :alt: stepped_isochrone_separate_15_min
+ :align: center
+ :width: 80%
+
+ **Separate stepped zones** visualized per time interval.
+
+----
+
+Example notebook
+----------------
+
+:doc:`examples/isochrones`
\ No newline at end of file
diff --git a/docs/methods/noise.rst b/docs/methods/noise.rst
new file mode 100644
index 0000000..9a08489
--- /dev/null
+++ b/docs/methods/noise.rst
@@ -0,0 +1,66 @@
+Noise Simulation & Noise Frame
+==============================
+
+**Noise Simulation** models how sound propagates from one or more **source points**,
+taking into account **obstacles**, **vegetation**, and **environmental conditions**.
+The outputs are **noise exposure maps** that are useful for **urban planning**,
+**environmental impact assessments**, and **acoustic zoning**.
+
+----
+
+ The module provides several simulation methods depending on the required level of detail and computational performance.
+
+ - **Full wave-based simulation** — physically detailed modeling of sound propagation.
+ - **Simplified geometric frame** — faster approximate results for general assessments.
+
+----
+
+Full Wave-Based Simulation
+--------------------------
+
+Performs detailed noise modeling using **wave-based acoustic calculations**.
+This approach accounts for reflections, diffractions, and absorption by materials.
+
+.. autofunction:: objectnat.simulate_noise
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/noise_simulation_1point.png
+ :alt: noise_simulation_1point
+ :align: center
+ :width: 80%
+
+ Example of full wave-based simulation for a single noise source.
+
+----
+
+Simplified Noise Frame
+----------------------
+
+Generates a **simplified noise exposure map** using only **geometric visibility**
+and **sound decay with distance**, without running a full wave simulation.
+Ideal for **rapid assessments** or large-scale analyses where precision is less critical.
+
+.. autofunction:: objectnat.calculate_simplified_noise_frame
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/noise_frame.png
+ :alt: noise_frame
+ :align: center
+ :width: 80%
+
+ Simplified geometric noise exposure frame — fast and efficient.
+
+----
+
+Additional Resources
+--------------------
+
+For comprehensive documentation and advanced configuration options,
+see the project Wiki:
+
+`Noise Simulation on GitHub `_
+
+----
+
+Example notebook
+----------------
+
+:doc:`examples/noise`
\ No newline at end of file
diff --git a/docs/methods/provision.rst b/docs/methods/provision.rst
new file mode 100644
index 0000000..3ccb52f
--- /dev/null
+++ b/docs/methods/provision.rst
@@ -0,0 +1,75 @@
+Service Provision Analysis
+==========================
+
+This module evaluates how well **services** (e.g., schools, clinics, shops)
+cover **residential buildings** based on their **capacity** and **accessibility**.
+It models **demand–supply relationships** and provides tools to analyze, visualize,
+and adjust service coverage.
+
+----
+
+ Service provision analysis helps estimate how effectively urban infrastructure
+ meets population needs.
+
+----
+
+Evaluate Initial Provision
+--------------------------
+
+Calculates **provision scores** between population points and service facilities
+considering:
+
+- **Distance or time thresholds**
+- **Facility capacity**
+- **Demand distribution**
+
+.. autofunction:: objectnat.get_service_provision
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/service_provision_initial.png
+ :alt: service_provision_initial
+ :align: center
+ :width: 80%
+
+ Initial service provision analysis — demand–supply balance based on accessibility.
+
+----
+
+Recalculate Provision
+---------------------
+
+Allows recalculation of provision results with **new accessibility thresholds**
+**without recomputing the full OD-matrix**, saving computation time.
+
+.. autofunction:: objectnat.recalculate_links
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/service_provision_recalculated.png
+ :alt: service_provision_recalculated
+ :align: center
+ :width: 80%
+
+ Recalculated provision results using adjusted travel-time thresholds.
+
+----
+
+Clip to Analysis Area
+---------------------
+
+Restricts provision outputs to a given **geographic boundary**
+(e.g., administrative region, neighborhood, planning area).
+
+.. autofunction:: objectnat.clip_provision
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/service_provision_clipped.png
+ :alt: service_provision_clipped
+ :align: center
+ :width: 80%
+
+ Provision results clipped to a selected administrative boundary.
+
+----
+
+Example notebook
+----------------
+
+:doc:`examples/calculate_adjacency_matrix`
+:doc:`examples/provision`
\ No newline at end of file
diff --git a/docs/methods/visibility.rst b/docs/methods/visibility.rst
new file mode 100644
index 0000000..580589b
--- /dev/null
+++ b/docs/methods/visibility.rst
@@ -0,0 +1,67 @@
+Visibility Analysis
+===================
+
+**Visibility analysis** estimates which **buildings** or **areas** are visible from
+a given observer point (or set of points) within a specified distance.
+It is useful for studying **visual accessibility**, **urban morphology**, and
+**perceptual exposure** in public spaces.
+
+----
+
+ The module supports several modes of visibility computation — from precise
+ raster-based modeling to fast vector-based approximations and multi-point visibility grids.
+
+----
+
+Accurate Method
+----------------
+
+Performs visibility analysis using **fine-grained raster-based algorithms**.
+Provides high spatial accuracy but is more computationally intensive.
+Best suited for detailed, local-scale visibility studies.
+
+.. autofunction:: objectnat.get_visibility_accurate
+
+----
+
+Fast Approximate Method
+-----------------------
+
+Optimized for **large datasets** or **regional-scale studies**.
+Uses geometric simplifications and **vector-based visibility** estimation,
+providing fast yet informative results.
+
+.. autofunction:: objectnat.get_visibility
+
+.. figure:: https://raw.githubusercontent.com/DDonnyy/ObjectNat/assets/visibility_comparison_methods.png
+ :alt: visibility_comparison_methods
+ :align: center
+ :width: 80%
+
+ Comparison between raster-based and vector-based visibility methods.
+
+----
+
+Catchment Visibility from Multiple Points
+-----------------------------------------
+
+Performs visibility analysis for a **dense grid of observer points**,
+producing combined **catchment visibility zones** — areas showing where specific
+objects (e.g., landmarks, buildings) can be seen from.
+
+.. autofunction:: objectnat.get_visibilities_from_points
+
+.. figure:: https://github.com/user-attachments/assets/b5b0d4b3-a02f-4ade-8772-475703cd6435
+ :alt: visibility-catchment-area
+ :align: center
+ :width: 80%
+
+ Example of visibility polygons aggregated into **visibility pools** —
+ zones most visible from multiple locations in an urban environment.
+
+----
+
+Example notebook
+----------------
+
+:doc:`examples/visibility`
\ No newline at end of file
diff --git a/docs/usage/coverage.md b/docs/usage/coverage.md
deleted file mode 100644
index 09ea9b7..0000000
--- a/docs/usage/coverage.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# **Coverage Zones**
-
-Coverage zones show areas that can be reached from each of multiple source points within a certain time or distance limit using a transport network.
-They are built by calculating reachability per point, generating Voronoi polygons, and optionally clipping them to a boundary.
-
----
-
-The library supports several methods for generating coverage zones:
-
-## **Coverage using transport graph**
-
-Uses a full routing engine to determine reachable areas per point, then builds zones.
-
-::: objectnat.get_graph_coverage
- options:
- show_root_heading: true
- heading_level: None
-
-
-
-
----
-
-## **Coverage using radius only**
-
-Generates fixed-radius buffers per point without routing, clipped via Voronoi.
-
-::: objectnat.get_radius_coverage
- options:
- show_root_heading: true
- heading_level: None
-
-
-
----
-
-## **Stepped graph coverage**
-
-Creates stepped zones (e.g., 5, 10, 15 minutes) using the full transport graph per point.
-
-::: objectnat.get_stepped_graph_coverage
- options:
- show_root_heading: true
- heading_level: None
-
-
-
-
----
-
diff --git a/docs/usage/isochrones.md b/docs/usage/isochrones.md
deleted file mode 100644
index 7f9ee2b..0000000
--- a/docs/usage/isochrones.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# **Isochrones and Transport Accessibility**
-
-Isochrones represent areas reachable from a starting point within a given time limit along a transport network.
-This function enables analysis of transport accessibility using pedestrian, automobile, public transport graphs, or their combination.
-
----
-
-The library offers multiple isochrone generation methods:
-
-## **Baseline isochrones**
-Show a single area reachable within a specified time.
-
-::: objectnat.get_accessibility_isochrones
- options:
- show_root_heading: true
- heading_level: None
-
-
-
-
-
----
-
-## **Stepped isochrones**
-Show accessibility ranges divided into time intervals (e.g., 5, 10, 15 minutes).
-
-::: objectnat.get_accessibility_isochrone_stepped
- options:
- show_root_heading: true
- heading_level: None
-
-
-
-
-
----
\ No newline at end of file
diff --git a/docs/usage/noise.md b/docs/usage/noise.md
deleted file mode 100644
index 16fcb3a..0000000
--- a/docs/usage/noise.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# **Noise Simulation**
-
-Noise Simulation models how sound propagates from one or more source points, taking into account **obstacles**, **vegetation**, and environmental conditions.
-The outputs are noise exposure maps useful for urban planning and environmental impact assessments.
-
----
-
-The module provides two methods:
-
-## **Full Wave-Based Simulation**
-
-Performs detailed noise modeling using full wave-based calculations.
-
-::: objectnat.simulate_noise
- options:
- show_root_heading: true
- heading_level: None
-
-
-
-
----
-
-## **Simplified Noise Frame**
-
-Creates a simplified noise exposure map using only geometric visibility and sound decay, without full wave simulation. Ideal for quick results.
-
-::: objectnat.calculate_simplified_noise_frame
- options:
- show_root_heading: true
- heading_level: None
-
-
-
----
-
-## More Details
-
-For comprehensive documentation and advanced configuration options, see the project Wiki:
-[Noise Simulation on GitHub](https://github.com/DDonnyy/ObjectNat/wiki/Noise-simulation)
diff --git a/docs/usage/provision.md b/docs/usage/provision.md
deleted file mode 100644
index c6b895b..0000000
--- a/docs/usage/provision.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# **Service Provision Analysis**
-
-This module evaluates how well services (e.g., schools, clinics) cover residential buildings based on their **capacity** and **accessibility**.
-It models demand-supply relationships and provides tools to analyze and adjust service coverage.
-
----
-
-## **Evaluate initial provision**
-
-Calculates provision scores between population points and service facilities considering:
-
-- Distance or time threshold,
-- Facility capacity,
-- Demand distribution.
-
-::: objectnat.get_service_provision
- options:
- show_root_heading: true
- heading_level: None
-
-
-
----
-
-## **Recalculate provision**
-
-Allows you to recalculate provision results with new accessibility thresholds without recomputing the full OD-matrix.
-
-::: objectnat.recalculate_links
- options:
- show_root_heading: true
- heading_level: None
-
-
-
----
-
-## **Clip to analysis area**
-
-Restricts provision output to a given geographic boundary (e.g., administrative area).
-
-::: objectnat.clip_provision
- options:
- show_root_heading: true
- heading_level: None
-
-
-
----
-
-## Graph Preparation via IduEdu
-
-For best performance and reproducibility, it is recommended to build or download intermodal graphs using the [`IduEdu`](https://pypi.org/project/iduedu/) library.
-
-Here is a minimal example:
-
-```python
-# Install required packages (uncomment if needed)
-# !pip install iduedu
-
-from iduedu import get_boundary, get_intermodal_graph
-
-# Load boundary and graph for a specific region using OSM ID 1114252.
-poly = get_boundary(osm_id=1114252)
-G_intermodal = get_intermodal_graph(polygon=poly, clip_by_bounds=True)
-```
\ No newline at end of file
diff --git a/docs/usage/visibility.md b/docs/usage/visibility.md
deleted file mode 100644
index dcd99fa..0000000
--- a/docs/usage/visibility.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# **Visibility Analysis**
-
-Visibility analysis estimates which buildings or areas are visible from a given observer point (or set of points)
-within a specific distance. This is useful in assessing **visual accessibility**, urban form,
-and perceptual exposure in public space.
-
----
-
-The module supports multiple modes of analysis:
-
-## **Accurate Method**
-
-Computes visibility using fine-grained raster-based methods. More accurate for local areas, but slower.
-
-::: objectnat.get_visibility_accurate
- options:
- show_root_heading: true
- heading_level: None
-
----
-
-## **Fast Approximate Method**
-
-Optimized for large datasets or large areas. Uses geometry simplifications and vector-based visibility.
-
-::: objectnat.get_visibility
- options:
- show_root_heading: true
- heading_level: None
-
-
-
----
-
-## **Catchment Visibility from Multiple Points**
-
-Performs visibility analysis for a dense grid of observer points.
-Used to generate **catchment areas** of visibility (e.g., “where can this building be seen from?”).
-
-::: objectnat.get_visibilities_from_points
- options:
- show_root_heading: true
- heading_level: None
-
----
-
-_The image below shows an example of using visibility polygons to calculate "visibility pools" - areas in an urban
-environment that are most visible from different locations._
-
-
-
----
diff --git a/mkdocs.yml b/mkdocs.yml
deleted file mode 100644
index 240f214..0000000
--- a/mkdocs.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-site_name: ObjectNat
-site_url: https://ddonnyy.github.io/ObjectNat/
-use_directory_urls: false
-
-theme:
- language: en
- name: material
- features:
- - navigation.expand
- - versioning
- palette:
- # Palette toggle for automatic mode
- - media: "(prefers-color-scheme)"
- toggle:
- icon: material/brightness-auto
- name: Switch to light mode
- # Palette toggle for light mode
- - media: "(prefers-color-scheme: light)"
- scheme: default
- toggle:
- icon: material/brightness-7
- name: Switch to dark mode
- # Palette toggle for dark mode
- - media: "(prefers-color-scheme: dark)"
- scheme: slate
- toggle:
- icon: material/brightness-4
- name: Switch to system preference
-
-plugins:
- - search
- - mike
- - mkdocstrings:
- handlers:
- python:
- paths: [ src ]
-
-extra:
- version:
- provider: mike
-
-markdown_extensions:
- - admonition
- - codehilite
- - toc:
- permalink: true
-
-nav:
- - Home: index.md
- - Usage:
- - Isochrones: usage/isochrones.md
- - Coverage Zones: usage/coverage.md
- - Service Provision: usage/provision.md
- - Visibility: usage/visibility.md
- - Noise Simulation: usage/noise.md
- - Clustering: usage/clustering.md
- - API Reference: api.md
-
-watch:
- - src
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index 08d28e0..1210bec 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,41 +1,49 @@
[tool.poetry]
name = "ObjectNat"
-version = "1.2.2"
+version = "1.3.0"
description = "ObjectNat is an open-source library created for geospatial analysis created by IDU team"
license = "BSD-3-Clause"
authors = ["DDonnyy <63115678+DDonnyy@users.noreply.github.com>"]
-readme = "README.md"
+readme = "README.rst"
packages = [{ include = "objectnat", from = "src" }]
[tool.poetry.dependencies]
-python = ">=3.10,<3.13"
+python = ">=3.11,<3.13"
numpy = "^2.1.3"
pandas = "^2.2.0"
geopandas = "^1.0.1"
tqdm = "^4.66.2"
-pandarallel = "^1.6.5"
networkx = "^3.4.2"
scikit-learn = "^1.4.0"
loguru = "^0.7.3"
+
+[tool.poetry.group.test.dependencies]
+pytest = "^8.3.5"
+pytest-cov = "^6.0.0"
+folium = "^0.19.5"
+matplotlib = "^3.10.1"
+mapclassify = "^2.8.1"
+iduedu = "^1.0.0"
+
[tool.poetry.group.dev.dependencies]
-iduedu = "^0.5.0"
pyarrow = "^19.0.1"
black = "^24.2.0"
pylint = "^3.0.3"
isort = "^5.13.2"
jupyter = "^1.0.0"
-pytest = "^8.3.5"
-pytest-cov = "^6.0.0"
pre-commit = "^4.2.0"
-folium = "^0.19.5"
-matplotlib = "^3.10.1"
-mapclassify = "^2.8.1"
-mkdocs = "^1.6.1"
-mkdocstrings = {extras = ["python"], version = "^0.29.1"}
-mkdocs-material = "^9.6.14"
-mike = "^2.1.3"
+
+[tool.poetry.group.docs.dependencies]
+sphinx = "^8.0.0"
+furo = "^2025.9.25"
+myst-nb = "^1.1.0"
+sphinx-autodoc-typehints = "^3.2.0"
+sphinx-copybutton = "^0.5.2"
+sphinx-design = "^0.6.0"
+myst-parser = "^4.0.1"
+linkify-it-py = "^2.0.3"
[build-system]
requires = ["poetry-core"]
@@ -43,7 +51,7 @@ build-backend = "poetry.core.masonry.api"
[tool.black]
line-length = 120
-target-version = ['py310']
+target-version = ['py311']
[tool.pylint.format]
max-line-length = 120
diff --git a/src/objectnat/_config.py b/src/objectnat/_config.py
index dcf4f2c..5df86f5 100644
--- a/src/objectnat/_config.py
+++ b/src/objectnat/_config.py
@@ -30,7 +30,6 @@ def __init__(
):
self.enable_tqdm_bar = enable_tqdm_bar
self.logger = logger
- self.pandarallel_use_file_system = False
def change_logger_lvl(self, lvl: Literal["TRACE", "DEBUG", "INFO", "WARN", "ERROR"]):
self.logger.remove()
@@ -39,9 +38,6 @@ def change_logger_lvl(self, lvl: Literal["TRACE", "DEBUG", "INFO", "WARN", "ERRO
def set_enable_tqdm(self, enable: bool):
self.enable_tqdm_bar = enable
- def set_pandarallel_use_file_system(self, enable: bool):
- self.pandarallel_use_file_system = enable
-
config = Config()
config.change_logger_lvl("INFO")
diff --git a/src/objectnat/_version.py b/src/objectnat/_version.py
index fbe7cc2..7b49cf1 100644
--- a/src/objectnat/_version.py
+++ b/src/objectnat/_version.py
@@ -1 +1 @@
-VERSION = "1.2.2"
+VERSION = "1.3.0"
diff --git a/src/objectnat/methods/coverage_zones/graph_coverage.py b/src/objectnat/methods/coverage_zones/graph_coverage.py
index 91a83b3..84342e9 100644
--- a/src/objectnat/methods/coverage_zones/graph_coverage.py
+++ b/src/objectnat/methods/coverage_zones/graph_coverage.py
@@ -27,20 +27,27 @@ def get_graph_coverage(
4. Combining reachability information with Voronoi cells
5. Clipping results to specified zone boundary
- Parameters:
+ Args:
gdf_to (gpd.GeoDataFrame):
Source points to which coverage is calculated.
+
nx_graph (nx.Graph):
NetworkX graph representing the transportation network.
- weight_type (Literal["time_min", "length_meter"]):
- Edge attribute to use as weight for path calculations.
+
+ weight_type:
+ Type of edge weight to use for path calculation:
+
+ - ``"time_min"``: Edge travel time in minutes
+ - ``"length_meter"``: Edge length in meters
+
weight_value_cutoff (float):
Maximum weight value for path calculations (e.g., max travel time/distance).
+
zone (gpd.GeoDataFrame):
Boundary polygon to clip the resulting coverage zones. If None, concave hull of reachable nodes will be used.
Returns:
- (gpd.GeoDataFrame):
+ gpd.GeoDataFrame:
GeoDataFrame with coverage zones polygons, each associated with its source point, returns in the same CRS
as original gdf_from.
diff --git a/src/objectnat/methods/coverage_zones/radius_voronoi_coverage.py b/src/objectnat/methods/coverage_zones/radius_voronoi_coverage.py
index 19830f9..12bfcdf 100644
--- a/src/objectnat/methods/coverage_zones/radius_voronoi_coverage.py
+++ b/src/objectnat/methods/coverage_zones/radius_voronoi_coverage.py
@@ -6,16 +6,18 @@ def get_radius_coverage(gdf_from: gpd.GeoDataFrame, radius: float, resolution: i
"""
Calculate radius-based coverage zones using Voronoi polygons.
- Parameters:
+ Args:
gdf_from (gpd.GeoDataFrame):
Source points for which coverage zones are calculated.
+
radius (float):
Maximum coverage radius in meters.
+
resolution (int):
Number of segments used to approximate quarter-circle in buffer (default=32).
Returns:
- (gpd.GeoDataFrame):
+ gpd.GeoDataFrame:
GeoDataFrame with smoothed coverage zone polygons in the same CRS as original gdf_from.
Notes:
diff --git a/src/objectnat/methods/coverage_zones/stepped_coverage.py b/src/objectnat/methods/coverage_zones/stepped_coverage.py
index 9293d16..50a9317 100644
--- a/src/objectnat/methods/coverage_zones/stepped_coverage.py
+++ b/src/objectnat/methods/coverage_zones/stepped_coverage.py
@@ -31,30 +31,40 @@ def get_stepped_graph_coverage(
4. Aggregates zones into stepped coverage layers
5. Optionally clips results to a boundary zone
- Parameters:
+ Args:
gdf_to (gpd.GeoDataFrame):
Source points from which stepped coverage is calculated.
+
nx_graph (nx.Graph):
NetworkX graph representing the transportation network.
- weight_type (Literal["time_min", "length_meter"]):
+
+ weight_type:
Type of edge weight to use for path calculation:
- - "time_min": Edge travel time in minutes
- - "length_meter": Edge length in meters
- step_type (Literal["voronoi", "separate"]):
+
+ - ``"time_min"``: Edge travel time in minutes
+ - ``"length_meter"``: Edge length in meters
+
+ step_type:
Method for generating stepped zones:
- - "voronoi": Stepped zones based on Voronoi polygons around graph nodes
- - "separate": Independent buffer zones per step
+
+ - ``"voronoi"``: Stepped zones based on Voronoi polygons around graph nodes
+ - ``"separate"``: Independent buffer zones per step
+
weight_value_cutoff (float, optional):
Maximum weight value (e.g., max travel time or distance) to limit the coverage extent.
+
zone (gpd.GeoDataFrame, optional):
Optional boundary polygon to clip resulting stepped zones. If None, concave hull of reachable area is used.
+
step (float, optional):
Step interval for coverage zone construction. Defaults to:
- - 100 meters for distance-based weight
- - 1 minute for time-based weight
+
+ - 100 meters for distance-based weight
+ - 1 minute for time-based weight
Returns:
- (gpd.GeoDataFrame): GeoDataFrame with polygons representing stepped coverage zones for each input point,
+ gpd.GeoDataFrame:
+ GeoDataFrame with polygons representing stepped coverage zones for each input point,
annotated by step range.
Notes:
diff --git a/src/objectnat/methods/isochrones/isochrones.py b/src/objectnat/methods/isochrones/isochrones.py
index 478b889..8d0a9d6 100644
--- a/src/objectnat/methods/isochrones/isochrones.py
+++ b/src/objectnat/methods/isochrones/isochrones.py
@@ -31,33 +31,44 @@ def get_accessibility_isochrone_stepped(
"""
Calculate stepped accessibility isochrones for a single point with specified intervals.
- Parameters:
- isochrone_type (Literal["radius", "ways", "separate"]):
+ Args:
+ isochrone_type:
Visualization method for stepped isochrones:
- - "radius": Voronoi-based in circular buffers
- - "ways": Voronoi-based in road network polygons
- - "separate": Circular buffers for each step
+
+ - ``"radius"``: Voronoi-based in circular buffers
+ - ``"ways"``: Voronoi-based in road network polygons
+ - ``"separate"``: Circular buffers for each step
+
point (gpd.GeoDataFrame):
Single source point for isochrone calculation (uses first geometry if multiple provided).
+
weight_value (float):
Maximum travel time (minutes) or distance (meters) threshold.
- weight_type (Literal["time_min", "length_meter"]):
+
+ weight_type:
Type of weight calculation:
+
- "time_min": Time-based in minutes
- "length_meter": Distance-based in meters
+
nx_graph (nx.Graph):
NetworkX graph representing the transportation network.
+
step (float, optional):
Interval between isochrone steps. Defaults to:
+
- 100 meters for distance-based
- 1 minute for time-based
+
**kwargs: Additional parameters:
+
- buffer_factor: Size multiplier for buffers (default: 0.7)
- road_buffer_size: Buffer size for road edges in meters (default: 5)
Returns:
- (tuple[gpd.GeoDataFrame, gpd.GeoDataFrame | None, gpd.GeoDataFrame | None]):
+ tuple[gpd.GeoDataFrame, gpd.GeoDataFrame | None, gpd.GeoDataFrame | None]:
Tuple containing:
+
- stepped_isochrones: GeoDataFrame with stepped polygons and distance/time attributes
- pt_stops: Public transport stops within isochrones (if available)
- pt_routes: Public transport routes within isochrones (if available)
@@ -150,29 +161,38 @@ def get_accessibility_isochrones(
- 'radius': Circular buffer-based isochrones
- 'ways': Road network-based isochrones
- Parameters:
- isochrone_type (Literal["radius", "ways"]):
+ Args:
+ isochrone_type:
Type of isochrone to calculate:
+
- "radius": Creates circular buffers around reachable nodes
- "ways": Creates polygons based on reachable road network
+
points (gpd.GeoDataFrame):
GeoDataFrame containing source points for isochrone calculation.
+
weight_value (float):
Maximum travel time (minutes) or distance (meters) threshold.
- weight_type (Literal["time_min", "length_meter"]):
+
+ weight_type:
Type of weight calculation:
+
- "time_min": Time-based accessibility in minutes
- "length_meter": Distance-based accessibility in meters
+
nx_graph (nx.Graph):
NetworkX graph representing the transportation network.
Must contain CRS and speed attributes for time calculations.
+
**kwargs: Additional parameters:
+
- buffer_factor: Size multiplier for buffers (default: 0.7)
- road_buffer_size: Buffer size for road edges in meters (default: 5)
Returns:
- (tuple[gpd.GeoDataFrame, gpd.GeoDataFrame | None, gpd.GeoDataFrame | None]):
+ tuple[gpd.GeoDataFrame, gpd.GeoDataFrame | None, gpd.GeoDataFrame | None]:
Tuple containing:
+
- isochrones: GeoDataFrame with calculated isochrone polygons
- pt_stops: Public transport stops within isochrones (if available)
- pt_routes: Public transport routes within isochrones (if available)
diff --git a/src/objectnat/methods/noise/noise_simulation.py b/src/objectnat/methods/noise/noise_simulation.py
index 9b2b21c..bda5cce 100644
--- a/src/objectnat/methods/noise/noise_simulation.py
+++ b/src/objectnat/methods/noise/noise_simulation.py
@@ -35,7 +35,7 @@ def simulate_noise(
"""
Simulates noise propagation from a set of source points considering obstacles, trees, and environmental factors.
- Parameters:
+ Args:
source_points (gpd.GeoDataFrame):
A GeoDataFrame with one or more point geometries representing noise sources.
Optionally, it can include 'source_noise_db' and 'geometric_mean_freq_hz' columns for per-point simulation.
@@ -53,32 +53,33 @@ def simulate_noise(
frequencies. It's recommended to use values between 63 Hz and 8000 Hz; values outside this range will be
clamped to the nearest boundary for the sound absorption coefficient calculation.
- Optional kwargs:
- - absorb_ratio_column (str, optional): The name of the column in the `obstacles` GeoDataFrame that contains the
+ Keyword Args:
+ absorb_ratio_column (str, optional): The name of the column in the `obstacles` GeoDataFrame that contains the
sound absorption coefficients for each obstacle. Default is None. If not specified, all obstacles will have
the `standart_absorb_ratio`.
- - standart_absorb_ratio (float, optional): The default sound absorption coefficient to use for obstacles without
+ standart_absorb_ratio (float, optional): The default sound absorption coefficient to use for obstacles without
specified values in the `absorb_ratio_column`. Default is 0.05, which is a typical value for concrete walls.
- - trees (gpd.GeoDataFrame, optional): A GeoDataFrame containing trees or dense vegetation along the sound wave's
+ trees (gpd.GeoDataFrame, optional): A GeoDataFrame containing trees or dense vegetation along the sound wave's
path. Trees will scatter and absorb sound waves.
- - tree_resolution (int, optional): A resolution parameter for simulating tree interactions with sound waves.
+ tree_resolution (int, optional): A resolution parameter for simulating tree interactions with sound waves.
Recommended values are between 2 and 16, with higher values providing more accurate simulation results.
- - air_temperature (float, optional): The air temperature in degrees Celsius. The recommended range is from 0 to
+ air_temperature (float, optional): The air temperature in degrees Celsius. The recommended range is from 0 to
30 degrees Celsius, as temperatures outside this range will be clipped. Temperature affects the sound
propagation in the air.
- - target_noise_db (float, optional): The target noise level (in dB) for the simulation. Default is 40 dB.
+ target_noise_db (float, optional): The target noise level (in dB) for the simulation. Default is 40 dB.
Lower values may not be relevant for further analysis, as they are near the threshold of human hearing.
- - db_sim_step (float, optional): The step size in decibels for the noise simulation. Default is 1. For more
+ db_sim_step (float, optional): The step size in decibels for the noise simulation. Default is 1. For more
precise analysis, this can be adjusted. If the difference between `source_noise_db` and `target_noise_db`
is not divisible by the step size, the function will raise an error.
- - reflection_n (int, optional): The maximum number of reflections (bounces) to simulate for each sound wave.
+ reflection_n (int, optional): The maximum number of reflections (bounces) to simulate for each sound wave.
Recommended values are between 1 and 3. Larger values will result in longer simulation times.
- - dead_area_r (float, optional): A debugging parameter that defines the radius of the "dead zone" for reflections.
+ dead_area_r (float, optional): A debugging parameter that defines the radius of the "dead zone" for reflections.
Points within this area will not generate reflections. This is useful to prevent the algorithm from getting
stuck in corners or along building walls.
- - use_parallel (bool, optional): Whether to use ProcessPool for task distribution or not. Default is True.
+ use_parallel (bool, optional): Whether to use ProcessPool for task distribution or not. Default is True.
+
Returns:
- (gpd.GeoDataFrame): A GeoDataFrame containing the noise simulation results, including noise levels and geometries
+ gpd.GeoDataFrame: A GeoDataFrame containing the noise simulation results, including noise levels and geometries
of the affected areas. Each point's simulation results will be merged into a single GeoDataFrame.
"""
# Obstacles args
diff --git a/src/objectnat/methods/noise/noise_simulation_simplified.py b/src/objectnat/methods/noise/noise_simulation_simplified.py
index 6dbc45d..56cb6d6 100644
--- a/src/objectnat/methods/noise/noise_simulation_simplified.py
+++ b/src/objectnat/methods/noise/noise_simulation_simplified.py
@@ -31,9 +31,10 @@ def calculate_simplified_noise_frame(
Args:
noise_sources (gpd.GeoDataFrame): A GeoDataFrame containing geometries of noise sources (Point, LineString,
or Polygon). Each feature must have the following two columns:
- - 'source_noise_db': Initial sound level at the source, in decibels (dB).
- - 'geometric_mean_freq_hz': Characteristic sound frequency (Hz) used to model distance-based
- attenuation.
+
+ - 'source_noise_db': Initial sound level at the source, in decibels (dB).
+ - 'geometric_mean_freq_hz': Characteristic sound frequency (Hz) used to model distance-based attenuation.
+
Values in 'source_noise_db' must not exceed the physical maximum of 194 dB. Missing or NaN values in
required fields will raise an error.
@@ -45,21 +46,21 @@ def calculate_simplified_noise_frame(
attenuation model of sound in the atmosphere. Temperatures significantly outside the typical 0–30°C
range may lead to inaccurate results.
- Optional kwargs:
- - target_noise_db (float, optional): The minimum sound level threshold (in dB) to be modeled. Any value below
+ Keyword Args:
+ target_noise_db (float, optional): The minimum sound level threshold (in dB) to be modeled. Any value below
this threshold is considered insignificant and will be excluded from the resulting noise frame.
Default is 40 dB.
- - db_sim_step (float, optional): The simulation step size (in dB) used to discretize sound levels into
+ db_sim_step (float, optional): The simulation step size (in dB) used to discretize sound levels into
spatial layers. Default is 5. Smaller values produce more detailed output but increase computation time.
- - linestring_point_radius (float, optional): The spacing radius (in meters) used when converting LineString
+ linestring_point_radius (float, optional): The spacing radius (in meters) used when converting LineString
geometries into distributed point sources for simulation. Default is 30. Reducing this value improves
detail along long lines.
- - polygon_point_radius (float, optional): The point spacing (in meters) for distributing sources within
+ polygon_point_radius (float, optional): The point spacing (in meters) for distributing sources within
Polygon geometries. Default is 15. Points are sampled across the polygon’s surface and perimeter to
represent the full sound-emitting area.
Returns:
- (gpd.GeoDataFrame): A GeoDataFrame representing simplified noise distribution areas. The output geometries
+ gpd.GeoDataFrame: A GeoDataFrame representing simplified noise distribution areas. The output geometries
are polygons where each polygon is associated with the maximum sound level (in dB) present in that area,
as derived from overlapping source zones. The resulting data is dissolved by noise level and returned in
the original coordinate reference system (CRS) of the input sources.
diff --git a/src/objectnat/methods/point_clustering/cluster_points_in_polygons.py b/src/objectnat/methods/point_clustering/cluster_points_in_polygons.py
index 920f25a..82559b5 100644
--- a/src/objectnat/methods/point_clustering/cluster_points_in_polygons.py
+++ b/src/objectnat/methods/point_clustering/cluster_points_in_polygons.py
@@ -39,7 +39,7 @@ def get_clusters_polygon(
Generate cluster polygons for given points based on a specified minimum distance and minimum points per cluster.
Optionally, calculate the relative ratio between types of points within the clusters.
- Parameters:
+ Args:
points (gpd.GeoDataFrame):
GeoDataFrame containing the points to be clustered.
Must include a 'service_code' column for service ratio calculations.
@@ -47,13 +47,13 @@ def get_clusters_polygon(
Minimum distance between points to be considered part of the same cluster. Defaults to 100.
min_point (int, optional):
Minimum number of points required to form a cluster. Defaults to 5.
- method (Literal["DBSCAN", "HDBSCAN"], optional):
+ method:
The clustering method to use. Must be either "DBSCAN" or "HDBSCAN". Defaults to "HDBSCAN".
service_code_column (str, optional):
Column, containing service type for relative ratio in clasterized polygons. Defaults to "service_code".
Returns:
- (tuple[gpd.GeoDataFrame, gpd.GeoDataFrame]):
+ tuple[gpd.GeoDataFrame, gpd.GeoDataFrame]:
A tuple containing the clustered polygons GeoDataFrame and the original points GeoDataFrame with cluster labels.
"""
if method not in ["DBSCAN", "HDBSCAN"]:
diff --git a/src/objectnat/methods/provision/provision.py b/src/objectnat/methods/provision/provision.py
index 96d5e48..53f632c 100644
--- a/src/objectnat/methods/provision/provision.py
+++ b/src/objectnat/methods/provision/provision.py
@@ -1,5 +1,3 @@
-from typing import Tuple
-
import geopandas as gpd
import numpy as np
import pandas as pd
@@ -18,29 +16,53 @@ def get_service_provision(
threshold: int,
buildings_demand_column: str = "demand",
services_capacity_column: str = "capacity",
- pandarallel_init_kwargs: dict = None,
-) -> Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]:
- """Calculate load from buildings with demands on the given services using the distances matrix between them.
+) -> tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]:
+ """
+ Compute service provision between demand locations (buildings) and service facilities.
- Parameters:
- services (gpd.GeoDataFrame):
- GeoDataFrame of services
- adjacency_matrix (pd.DataFrame):
- DataFrame representing the adjacency matrix
+ The function implements a **gravity-based allocation model**: service capacity is
+ distributed across nearby demand points with weights that **decay with the square
+ of distance (or generalized cost)**. Closer buildings receive proportionally
+ higher shares of the available capacity.
+
+ Args:
buildings (gpd.GeoDataFrame):
- GeoDataFrame of demanded buildings
+ GeoDataFrame of **demand locations** (e.g., residential buildings).
+ Must include a numeric column with demand values
+ (see ``buildings_demand_column``).
+ adjacency_matrix (pd.DataFrame):
+ A rectangular DataFrame representing **OD (origin–destination) costs**
+ between ``buildings`` (rows) and ``services`` (columns).
+ Units must match ``threshold`` (e.g., minutes or meters).
+ Missing or infinite values (``NaN`` or ``inf``) are treated as **unreachable**.
+ The row index must match ``buildings.index`` and column index must
+ match ``services.index``.
+ services (gpd.GeoDataFrame):
+ GeoDataFrame of **service facilities** (e.g., schools, clinics).
+ Must include a numeric column with service capacity
+ (see ``services_capacity_column``).
threshold (int):
- Threshold value
+ Maximum allowed cost value for assignment.
+ Any OD entry **greater than this threshold** is considered unreachable.
+ Units are the same as in ``adjacency_matrix``.
buildings_demand_column (str):
- column name of buildings demands
+ Column name of building demand values. Default is ``"demand"``.
services_capacity_column (str):
- column name of services capacity
- pandarallel_init_kwargs (dict):
- Dictionary of keyword arguments to pass to pandarallel
+ Column name of service capacity values. Default is ``"capacity"``.
Returns:
- (Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]): Tuple of GeoDataFrames representing provision
- buildings, provision services, and provision links
+ Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]:
+ A tuple of three GeoDataFrames:
+
+ - **buildings**: input buildings with updated provision metrics.
+ - **services**: input services with updated load and capacity metrics.
+ - **links**: building–service links within the threshold, containing
+ allocated demand shares and distances/costs based on the gravity model.
+
+ Notes:
+ - The model is **gravity-based**, with cost weights decaying by the **square of distance**.
+ - Unreachable OD pairs (``NaN`` or ``inf``) are ignored.
+ - The function does not perform routing; it expects a precomputed OD matrix.
"""
buildings = buildings.copy()
services = services.copy()
@@ -53,15 +75,42 @@ def get_service_provision(
demanded_buildings=buildings,
adjacency_matrix=adjacency_matrix,
threshold=threshold,
- pandarallel_init_kwargs=pandarallel_init_kwargs,
).run()
return provision_buildings, provision_services, provision_links
def clip_provision(
buildings: gpd.GeoDataFrame, services: gpd.GeoDataFrame, links: gpd.GeoDataFrame, selection_zone: gpd.GeoDataFrame
-) -> Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]:
+) -> tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]:
+ """
+ Clip service provision results to a specific geographic boundary.
+
+ Keeps only:
+ * buildings that intersect the ``selection_zone``;
+ * links that connect to the kept buildings;
+ * services referenced by those links.
+
+ Args:
+ buildings:
+ GeoDataFrame of buildings **after** :func:`get_service_provision`.
+ services:
+ GeoDataFrame of services **after** :func:`get_service_provision`.
+ links:
+ GeoDataFrame of building–service links from
+ :func:`get_service_provision`. Must include indices or columns
+ to match buildings and services.
+ selection_zone:
+ GeoDataFrame (polygon or multipolygon) defining the clipping area.
+
+ Returns:
+ Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]:
+ The filtered subsets of buildings, services, and links
+ that fall inside the specified zone.
+ Notes:
+ - The function performs **spatial filtering only**.
+ It does **not** recompute or redistribute demand/supply.
+ """
assert selection_zone.crs == buildings.crs == services.crs == links.crs, (
f"CRS mismatch: buildings_crs:{buildings.crs}, "
f"links_crs:{links.crs} , "
@@ -83,6 +132,49 @@ def clip_provision(
def recalculate_links(
buildings: gpd.GeoDataFrame, services: gpd.GeoDataFrame, links: gpd.GeoDataFrame, new_max_dist: float
) -> tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]:
+ """
+ Recalculate provision aggregates after tightening the accessibility threshold.
+
+ Removes all links whose cost (distance or time) exceeds ``new_max_dist``, then
+ updates demand and capacity aggregates accordingly. This is done **without
+ redistributing** removed demand to alternative services.
+
+ Args:
+ buildings:
+ GeoDataFrame of buildings after :func:`get_service_provision`.
+ Expected to include provision-related fields such as demand, demand_left,
+ supplied demand, and average distance/cost.
+
+ services:
+ GeoDataFrame of services after :func:`get_service_provision`, with
+ fields describing remaining capacity and service load.
+
+ links:
+ GeoDataFrame of building–service links containing at least:
+
+ - ``building_index``
+ - ``service_index``
+ - ``distance`` (or time cost, in the same units as ``new_max_dist``)
+ - ``demand`` (assigned portion)
+
+ new_max_dist:
+ New maximum allowed cost value (same units as OD/threshold).
+ Links with cost **greater than** this value are removed.
+
+ Returns:
+ tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]:
+ - **buildings**: updated aggregate demand metrics and recalculated
+ average cost.
+ - **services**: updated load and capacity fields after freeing excess capacity.
+ - **links**: subset of links that remain within the new threshold.
+
+ Notes:
+ - If no links exceed ``new_max_dist``, the function logs a warning
+ and returns the original inputs unchanged.
+ - Average cost values are recomputed based on remaining links.
+ If a building has no remaining assigned demand, ``avg_dist`` becomes ``NaN``.
+ - Removed demand is **not reallocated** to other services.
+ """
buildings = buildings.copy()
services = services.copy()
links = links.copy()
diff --git a/src/objectnat/methods/provision/provision_model.py b/src/objectnat/methods/provision/provision_model.py
index 84136c5..790db58 100644
--- a/src/objectnat/methods/provision/provision_model.py
+++ b/src/objectnat/methods/provision/provision_model.py
@@ -4,7 +4,6 @@
import geopandas as gpd
import numpy as np
import pandas as pd
-from pandarallel import pandarallel
from shapely import LineString
from objectnat import config
@@ -40,7 +39,6 @@ def __init__(
demanded_buildings: gpd.GeoDataFrame,
adjacency_matrix: pd.DataFrame,
threshold: int,
- pandarallel_init_kwargs: dict = None,
):
self.services = self.ensure_services(services.copy())
self.demanded_buildings = self.ensure_buildings(demanded_buildings.copy())
@@ -50,16 +48,6 @@ def __init__(
self.threshold = threshold
self.services.to_crs(self.demanded_buildings.crs, inplace=True)
- if pandarallel_init_kwargs is None:
- pandarallel_init_kwargs = {}
-
- pandarallel_init_kwargs["use_memory_fs"] = pandarallel_init_kwargs.get(
- "use_memory_fs", config.pandarallel_use_file_system
- )
- pandarallel_init_kwargs["progress_bar"] = pandarallel_init_kwargs.get("progress_bar", False)
- pandarallel_init_kwargs["verbose"] = pandarallel_init_kwargs.get("verbose", 0)
- pandarallel.initialize(**pandarallel_init_kwargs)
-
@staticmethod
def ensure_buildings(v: gpd.GeoDataFrame) -> gpd.GeoDataFrame:
if "demand" not in v.columns:
@@ -91,17 +79,8 @@ def delete_useless_matrix_rows_columns(adjacency_matrix, demanded_buildings, ser
def run(self) -> Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]:
- def apply_function_based_on_size(df, func, axis, threshold=100):
- if len(df) > threshold:
- return df.parallel_apply(func, axis=axis)
- return df.apply(func, axis=axis)
-
def calculate_flows_y(loc):
- import numpy as np # pylint: disable=redefined-outer-name,reimported,import-outside-toplevel
- import pandas as pd # pylint: disable=redefined-outer-name,reimported,import-outside-toplevel
-
c = services_table.loc[loc.name]["capacity_left"]
- logger.debug(f"Capacity left: {c}")
p = 1 / loc / loc
p = p / p.sum()
threshold = p.quantile(best_houses)
@@ -117,9 +96,6 @@ def calculate_flows_y(loc):
return choice
def balance_flows_to_demands(loc):
- import numpy as np # pylint: disable=redefined-outer-name,reimported,import-outside-toplevel
- import pandas as pd # pylint: disable=redefined-outer-name,reimported,import-outside-toplevel
-
d = houses_table.loc[loc.name]["demand_left"]
loc = loc[loc > 0]
if loc.sum() > 0:
@@ -170,12 +146,11 @@ def balance_flows_to_demands(loc):
f" Best houses: {best_houses}"
)
- temp_destination_matrix = apply_function_based_on_size(
- distance_matrix, lambda x: calculate_flows_y(x[x <= selection_range]), 1
+ temp_destination_matrix = distance_matrix.apply(
+ lambda x: calculate_flows_y(x[x <= selection_range]), axis=1
)
-
temp_destination_matrix = temp_destination_matrix.fillna(0)
- temp_destination_matrix = apply_function_based_on_size(temp_destination_matrix, balance_flows_to_demands, 0)
+ temp_destination_matrix = temp_destination_matrix.apply(balance_flows_to_demands, axis=0)
temp_destination_matrix = temp_destination_matrix.fillna(0)
temp_destination_matrix_aligned = temp_destination_matrix.reindex(
index=destination_matrix.index, columns=destination_matrix.columns, fill_value=0
diff --git a/src/objectnat/methods/utils/graph_utils.py b/src/objectnat/methods/utils/graph_utils.py
index 39301cf..f6e7894 100644
--- a/src/objectnat/methods/utils/graph_utils.py
+++ b/src/objectnat/methods/utils/graph_utils.py
@@ -51,7 +51,7 @@ def graph_to_gdf(
"""
Converts nx graph to gpd.GeoDataFrame as edges.
- Parameters:
+ Args:
graph (nx.MultiDiGraph):
The graph to convert.
edges (bool):
@@ -98,7 +98,7 @@ def gdf_to_graph(
Intersections are optionally checked and merged. Attributes from the original GeoDataFrame
can be projected onto the graph edges using spatial matching.
- Parameters:
+ Args:
gdf (gpd.GeoDataFrame): A GeoDataFrame containing at least one LineString geometry.
project_gdf_attr (bool): If True, attributes from the input GeoDataFrame will be spatially
projected onto the resulting graph edges. This can be an expensive operation for large datasets.
@@ -193,7 +193,7 @@ def get_closest_nodes_from_gdf(gdf: gpd.GeoDataFrame, nx_graph: nx.Graph) -> tup
"""
Finds the closest graph nodes to the geometries in a GeoDataFrame.
- Parameters
+ Args
----------
gdf : gpd.GeoDataFrame
GeoDataFrame with geometries for which the nearest graph nodes will be found.
@@ -228,7 +228,7 @@ def remove_weakly_connected_nodes(graph: nx.DiGraph) -> nx.DiGraph:
"""
Removes all nodes that are not part of the largest strongly connected component in the graph.
- Parameters
+ Args
----------
graph : nx.DiGraph
A directed NetworkX graph.
@@ -275,7 +275,7 @@ def reverse_graph(nx_graph: nx.Graph, weight: str) -> tuple[nx.Graph, nx.DiGraph
For directed graphs, the function returns a new graph with all edge directions reversed,
preserving the specified edge weight.
- Parameters
+ Args
----------
nx_graph : nx.Graph
Input NetworkX graph (can be directed or undirected).
diff --git a/src/objectnat/methods/utils/math_utils.py b/src/objectnat/methods/utils/math_utils.py
index 3676bba..1accc31 100644
--- a/src/objectnat/methods/utils/math_utils.py
+++ b/src/objectnat/methods/utils/math_utils.py
@@ -5,7 +5,7 @@ def min_max_normalization(data, new_min=0, new_max=1):
"""
Min-max normalization for a given array of data.
- Parameters
+ Args
----------
data: numpy.ndarray
Input data to be normalized.
diff --git a/src/objectnat/methods/visibility/visibility_analysis.py b/src/objectnat/methods/visibility/visibility_analysis.py
index 3ec07b1..05b0b71 100644
--- a/src/objectnat/methods/visibility/visibility_analysis.py
+++ b/src/objectnat/methods/visibility/visibility_analysis.py
@@ -4,7 +4,6 @@
import geopandas as gpd
import numpy as np
import pandas as pd
-from pandarallel import pandarallel
from shapely import LineString, MultiPolygon, Point, Polygon
from shapely.ops import unary_union
from tqdm.contrib.concurrent import process_map
@@ -28,7 +27,7 @@ def get_visibility_accurate(
"""
Function to get accurate visibility from a given point to buildings within a given distance.
- Parameters:
+ Args:
point_from (Point | gpd.GeoDataFrame):
The point or GeoDataFrame with 1 point from which the line of sight is drawn.
If Point is provided it should be in the same crs as obstacles.
@@ -165,7 +164,7 @@ def get_visibility(
"""
Function to get a quick estimate of visibility from a given point to buildings within a given distance.
- Parameters:
+ Args:
point_from (Point | gpd.GeoDataFrame):
The point or GeoDataFrame with 1 point from which the line of sight is drawn.
If Point is provided it should be in the same crs as obstacles.
@@ -239,7 +238,7 @@ def get_visibilities_from_points(
"""
Calculate visibility polygons from a set of points considering obstacles within a specified view distance.
- Parameters:
+ Args:
points (gpd.GeoDataFrame):
GeoDataFrame containing the points from which visibility is calculated.
obstacles (gpd.GeoDataFrame):
@@ -297,7 +296,7 @@ def calculate_visibility_catchment_area(
This function is designed to work with at least 1000 points spaced 10-20 meters apart for optimal results.
Points can be generated using a road graph.
- Parameters:
+ Args:
points (gpd.GeoDataFrame): GeoDataFrame containing the points from which visibility is calculated.
obstacles (gpd.GeoDataFrame): GeoDataFrame containing the obstacles that block visibility.
view_distance (int | float): The maximum distance from each point within which visibility is calculated.
@@ -313,21 +312,12 @@ def filter_geoms(x):
return x
def calc_group_factor(x):
- # pylint: disable-next=redefined-outer-name,reimported,import-outside-toplevel
- import numpy as np
-
return np.mean(x.new_ratio) * x.count_n
def unary_union_groups(x):
- # pylint: disable-next=redefined-outer-name,reimported,import-outside-toplevel
- from shapely import MultiPolygon
-
- # pylint: disable-next=redefined-outer-name,reimported,import-outside-toplevel
- from shapely.ops import unary_union
-
return unary_union(MultiPolygon(list(x["geometry"])).buffer(0))
- pandarallel.initialize(progress_bar=True, verbose=0)
+ raise NotImplementedError("This method is temporarily unsupported.")
local_crs = obstacles.estimate_utm_crs()
obstacles = obstacles.to_crs(local_crs)
@@ -370,7 +360,7 @@ def unary_union_groups(x):
all_in["count_n"] = all_in["index_right"].apply(len)
logger.info("Calculating intersection's parameters")
- all_in["factor"] = all_in.parallel_apply(calc_group_factor, axis=1)
+ # all_in["factor"] = all_in.parallel_apply(calc_group_factor, axis=1) # TODO replace pandarallel methods
threshold = all_in["factor"].quantile(0.3)
all_in = all_in[all_in["factor"] > threshold]
@@ -378,7 +368,9 @@ def unary_union_groups(x):
min_max_normalization(np.sqrt(all_in["factor"].values), new_min=1, new_max=5)
).astype(int)
logger.info("Calculating normalized groups geometry...")
- all_in = all_in.groupby("factor_normalized").parallel_apply(unary_union_groups).reset_index()
+ all_in = (
+ all_in.groupby("factor_normalized").parallel_apply(unary_union_groups).reset_index()
+ ) # TODO replace pandarallel methods
all_in = gpd.GeoDataFrame(data=all_in.rename(columns={0: "geometry"}), geometry="geometry", crs=32636)
all_in = all_in.explode(index_parts=True).reset_index(drop=True)
diff --git a/src/tests/conftest.py b/src/tests/conftest.py
index 9e0a481..a0c11c0 100644
--- a/src/tests/conftest.py
+++ b/src/tests/conftest.py
@@ -4,14 +4,14 @@
import geopandas as gpd
import pandas as pd
import pytest
-from iduedu import config, get_boundary, get_intermodal_graph
+from iduedu import config, get_4326_boundary, get_intermodal_graph
from shapely import Point
from objectnat import graph_to_gdf
logger = config.logger
-path_to_data = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../examples/examples_data/")
+path_to_data = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../docs/examples/examples_data/")
output_dir = os.path.join(os.path.dirname(__file__), "test_output")
cache_dir = os.path.join(os.path.dirname(__file__), "test_cache")
os.makedirs(cache_dir, exist_ok=True)
@@ -59,7 +59,7 @@ def trees_data():
@pytest.fixture(scope="session")
def boundary_osm_1114252():
- return get_boundary(osm_id=1114252)
+ return get_4326_boundary(osm_id=1114252)
@pytest.fixture(scope="session")
@@ -74,7 +74,7 @@ def intermodal_osm_1114252(boundary_osm_1114252):
logger.warning(f"Failed to load cached graph: {e}. Regenerating...")
os.remove(cache_file)
logger.info("Generating new intermodal graph")
- graph = get_intermodal_graph(polygon=boundary_osm_1114252, clip_by_bounds=True)
+ graph = get_intermodal_graph(territory=boundary_osm_1114252, clip_by_territory=True)
try:
with open(cache_file, "wb") as f:
logger.info(f"Saving graph to cache: {cache_file}")