sibi-dst 0.3.32__py3-none-any.whl → 0.3.34__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,64 @@ from folium.plugins import Fullscreen
11
11
 
12
12
 
13
13
  class BaseOsmMap:
14
+ """
15
+ BaseOsmMap class serves as a foundational class for creating and managing maps
16
+ using OpenStreetMap data. It integrates features from libraries like osmnx and
17
+ folium to facilitate visualization, tile layer management, bounding box handling,
18
+ and nearest node calculation for geographic coordinates.
19
+
20
+ The class is designed to be subclassed, enabling customization of map processing
21
+ logic while providing core functionalities needed for map creation and manipulation.
22
+
23
+ :ivar tile_options: Dictionary containing options for pre-defined tile layers.
24
+ Keys represent display names while values represent tile layer configurations.
25
+ :type tile_options: dict
26
+ :ivar bounds: Default map bounds representing geographical extents for Costa Rica.
27
+ :type bounds: list[list[float]]
28
+ :ivar osmnx_graph: Input graph representing OpenStreetMap network data, used for
29
+ operations like subgraph extraction and nearest node calculation.
30
+ :type osmnx_graph: networkx.classes.multidigraph.MultiDiGraph
31
+ :ivar df: DataFrame containing data points with geographic coordinates. It must
32
+ not be empty and should include latitude and longitude columns as specified
33
+ in `lat_col` and `lon_col`.
34
+ :type df: pandas.DataFrame
35
+ :ivar lat_col: Name of the column in `df` representing latitude coordinates of data points.
36
+ :type lat_col: str
37
+ :ivar lon_col: Name of the column in `df` representing longitude coordinates of data points.
38
+ :type lon_col: str
39
+ :ivar osm_map: Folium Map object that serves as a container for geographic visualization.
40
+ This is dynamically initialized based on the provided data.
41
+ :type osm_map: folium.Map
42
+ :ivar G: Subgraph of the provided `osmnx_graph`, extracted based on bounding box
43
+ derived from the input data.
44
+ :type G: networkx.classes.multidigraph.MultiDiGraph
45
+ :ivar map_html_title: HTML-escaped title for map visualization, shown on the interactive map.
46
+ :type map_html_title: str
47
+ :ivar zoom_start: Initial zoom level for the map when rendered.
48
+ :type zoom_start: int
49
+ :ivar fullscreen: Boolean option to enable or disable fullscreen control on the interactive map.
50
+ :type fullscreen: bool
51
+ :ivar fullscreen_position: Position of the fullscreen control on the map, e.g., 'topright'.
52
+ :type fullscreen_position: str
53
+ :ivar tiles: Default tile layer to be used for the map visualization.
54
+ :type tiles: str
55
+ :ivar verbose: Boolean flag indicating if verbose logging of operations should be enabled.
56
+ :type verbose: bool
57
+ :ivar sort_keys: Keys to sort the DataFrame by, if applicable, before processing.
58
+ :type sort_keys: list[str] or None
59
+ :ivar dt_field: Column name in `df` representing datetimes, if applicable, for specialized processing.
60
+ :type dt_field: str or None
61
+ :ivar dt: List of datetime objects extracted from `dt_field` in `df`, dynamically initialized.
62
+ :type dt: list[datetime.datetime] or None
63
+ :ivar calc_nearest_nodes: Boolean flag to indicate whether nearest nodes to the input
64
+ points should be calculated from `osmnx_graph`.
65
+ :type calc_nearest_nodes: bool
66
+ :ivar nearest_nodes: List of nearest node IDs for each point in the input data, if calculated.
67
+ :type nearest_nodes: list[int] or None
68
+ :ivar max_bounds: Boolean indicating whether bounds (default to Costa Rica) should be applied
69
+ to fit the map within those limits interactively.
70
+ :type max_bounds: bool
71
+ """
14
72
  tile_options = {
15
73
  "OpenStreetMap": "OpenStreetMap",
16
74
  "CartoDB": "cartodbpositron",
@@ -20,6 +78,47 @@ class BaseOsmMap:
20
78
  bounds = [[8.0340, -85.9417], [11.2192, -82.5566]]
21
79
 
22
80
  def __init__(self, osmnx_graph=None, df=None, **kwargs):
81
+ """
82
+ Initializes a map visualization handler with input parameters for managing and displaying
83
+ spatial data in conjunction with an OSMnx graph. It validates input parameters for completeness
84
+ and correctness, and configures internal attributes for the visualization of map layers.
85
+
86
+ :param osmnx_graph: The OSMnx graph to be used for spatial data processing.
87
+ :param df: The pandas DataFrame containing spatial data.
88
+ :param kwargs: Additional keyword arguments for customization.
89
+ :type osmnx_graph: object
90
+ :type df: pandas.DataFrame
91
+ :type kwargs: dict
92
+
93
+ :raises ValueError: If `osmnx_graph` is not provided.
94
+ :raises ValueError: If `df` is not provided.
95
+ :raises ValueError: If the provided `df` is empty.
96
+
97
+ :attribute df: A copy of the provided DataFrame.
98
+ :attribute osmnx_graph: The input OSMnx graph used for spatial data operations.
99
+ :attribute lat_col: The name of the column in `df` containing latitude values.
100
+ :attribute lon_col: The name of the column in `df` containing longitude values.
101
+ :attribute osm_map: Internal representation of the map; initialized to None.
102
+ :attribute G: Placeholder for graph-related data; initialized to None.
103
+ :attribute map_html_title: Sanitized HTML title to be used in rendered map outputs.
104
+ :attribute zoom_start: The initial zoom level for the map visualization (default: 13).
105
+ :attribute fullscreen: Boolean flag to enable fullscreen map display (default: True).
106
+ :attribute fullscreen_position: The position of the fullscreen control button
107
+ (default: 'topright').
108
+ :attribute tiles: The tile set to be used for the map visualization (default: 'OpenStreetMap').
109
+ :attribute verbose: Boolean flag for enabling verbose output (default: False).
110
+ :attribute sort_keys: Optional parameter dictating sorting order for keys (default: None).
111
+ :attribute dt_field: Optional name of the datetime field in the DataFrame (default: None).
112
+ :attribute dt: Placeholder for date/time data; initialized to None.
113
+ :attribute calc_nearest_nodes: Boolean flag to calculate nearest nodes to coordinates
114
+ (default: False).
115
+ :attribute nearest_nodes: Placeholder for nearest nodes data; initialized to None.
116
+ :attribute max_bounds: Boolean flag to restrict the map view to maximum bounds
117
+ (default: False).
118
+
119
+ :note: This class also initializes necessary internal functionalities including DataFrame
120
+ pre-processing (`_prepare_df`) and base map setup (`_initialise_map`).
121
+ """
23
122
  if osmnx_graph is None:
24
123
  raise ValueError('osmnx_graph must be provided')
25
124
  if df is None:
@@ -50,6 +149,21 @@ class BaseOsmMap:
50
149
 
51
150
 
52
151
  def _prepare_df(self):
152
+ """
153
+ Prepares the underlying DataFrame for further processing.
154
+
155
+ This method performs several operations on the DataFrame, such as sorting,
156
+ resetting the index, and extracting relevant columns into various lists.
157
+ Additionally, it calculates the nearest nodes from an OSMnx graph if
158
+ required. The operations are governed by instance attributes and their
159
+ current states.
160
+
161
+ :raises AttributeError: If required attributes for processing are not
162
+ correctly set or do not exist in the DataFrame.
163
+ :param self: Object that contains the DataFrame (df) and other related
164
+ attributes required for processing.
165
+ :return: None
166
+ """
53
167
  if self.sort_keys:
54
168
  self.df.sort_values(by=self.sort_keys, inplace=True)
55
169
  self.df.reset_index(drop=True, inplace=True)
@@ -63,6 +177,15 @@ class BaseOsmMap:
63
177
 
64
178
 
65
179
  def _initialise_map(self):
180
+ """
181
+ Initializes an OpenStreetMap (OSM) map instance and extracts a subgraph of map
182
+ data based on provided GPS points. The map's central location is calculated
183
+ as the mean of the latitudinal and longitudinal values of the GPS points.
184
+ Additionally, a bounding box is determined to extract the relevant section
185
+ of the map graph.
186
+
187
+ :return: None
188
+ """
66
189
  gps_array = np.array(self.gps_points)
67
190
  mean_latitude = np.mean(gps_array[:, 0])
68
191
  mean_longitude = np.mean(gps_array[:, 1])
@@ -73,6 +196,24 @@ class BaseOsmMap:
73
196
 
74
197
 
75
198
  def _attach_supported_tiles(self):
199
+ """
200
+ Attach supported tile layers from the provided tile options to the map object.
201
+
202
+ This method normalizes the default tile layer name and ensures that it is not
203
+ duplicated in the map by filtering out the default tile from the `tile_options`.
204
+ Then, it iterates over the filtered tile options and attaches each supported
205
+ tile layer to the map object using the folium library.
206
+
207
+ :raises KeyError: If any key in `tile_options` is invalid or not found.
208
+
209
+ :param self:
210
+ The instance of the class. It is expected to have the following attributes:
211
+ - tiles (str): The name of the default tile layer.
212
+ - tile_options (Dict[str, str]): A dictionary of tile layer names
213
+ and their associated URLs.
214
+ - osm_map (folium.Map): The map object to which tile layers are attached.
215
+ :return: None
216
+ """
76
217
  # Normalize the default tile name to lowercase for comparison
77
218
  normalized_default_tile = self.tiles.lower()
78
219
 
@@ -84,6 +225,22 @@ class BaseOsmMap:
84
225
 
85
226
 
86
227
  def _get_bounding_box_from_points(self, margin=0.001):
228
+ """
229
+ Calculate a bounding box from GPS points with an additional margin.
230
+
231
+ This method processes the GPS points in the `self.gps_points` list
232
+ and calculates a geographical bounding box encompassing all
233
+ points with an optional margin added to its boundaries. The
234
+ bounding box is defined by the northernmost, southernmost,
235
+ easternmost, and westernmost boundaries.
236
+
237
+ :param margin: A float value that adds a margin to the bounding
238
+ box boundaries.
239
+ Defaults to 0.001.
240
+ :return: A tuple containing four float values in the order:
241
+ north (northernmost boundary), south (southernmost boundary),
242
+ east (easternmost boundary), and west (westernmost boundary).
243
+ """
87
244
  latitudes = [point[0] for point in self.gps_points]
88
245
  longitudes = [point[1] for point in self.gps_points]
89
246
 
@@ -96,6 +253,26 @@ class BaseOsmMap:
96
253
 
97
254
 
98
255
  def _extract_subgraph(self, north, south, east, west):
256
+ """
257
+ Extracts a subgraph from the OSMnx graph based on a specified bounding box.
258
+
259
+ This function takes the northern, southern, eastern, and western bounds to
260
+ define a geographic bounding box. It creates a polygon from these bounds and
261
+ identifies nodes within the graph that fall within this boundary. A new subgraph
262
+ is then created using these identified nodes. This functionality supports different
263
+ approaches depending on the OSMnx version.
264
+
265
+ :param north: The northern boundary of the bounding box.
266
+ :type north: float
267
+ :param south: The southern boundary of the bounding box.
268
+ :type south: float
269
+ :param east: The eastern boundary of the bounding box.
270
+ :type east: float
271
+ :param west: The western boundary of the bounding box.
272
+ :type west: float
273
+ :return: A subgraph extracted from the OSMnx graph containing nodes within the bounding box.
274
+ :rtype: networkx.Graph
275
+ """
99
276
  # Create a bounding box polygon
100
277
  # from osmnx v2 this is how it is done
101
278
  if ox.__version__ >= '2.0':
@@ -117,18 +294,45 @@ class BaseOsmMap:
117
294
 
118
295
  @abstractmethod
119
296
  def process_map(self):
297
+ """
298
+ This abstract method serves as a blueprint for processing a map. It is intentionally
299
+ left unimplemented and must be overridden in any concrete subclass. Subclasses should
300
+ provide their own specific logic for map processing by implementing this interface.
301
+
302
+ :return: None
303
+ """
120
304
  # this is to be implemented at the subclass level
121
305
  # implement here your specific map logic.
122
306
  ...
123
307
 
124
308
 
125
309
  def pre_process_map(self):
310
+ """
311
+ Pre-processes the map data.
312
+
313
+ This method is designed to be overridden in a subclass to perform specific
314
+ pre-processing procedures on map data. When overridden, the implementation
315
+ in the subclass must call `super().pre_process_map` first to inherit and
316
+ maintain the existing behavior of this base implementation.
317
+
318
+ :return: None
319
+ """
126
320
  # this is to be implemented at the subclass level
127
321
  # call super().pre_process_map first to inherit the following behaviour
128
322
  ...
129
323
 
130
324
 
131
325
  def _post_process_map(self):
326
+ """
327
+ Performs post-processing tasks on the map object to enhance its functionality
328
+ and ensure required adjustments or attributes are attached to it. This method
329
+ is mainly used internally to finalize map setup based on current configurations.
330
+
331
+ :raises AttributeError: This error is raised if one of the required attributes
332
+ is not properly initialized or missing during the processing.
333
+ :raises ValueError: This error is raised if provided bounds are invalid or
334
+ incompatible for fitting.
335
+ """
132
336
  self._attach_supported_tiles()
133
337
  self.add_tile_layer()
134
338
  self._add_fullscreen()
@@ -138,26 +342,76 @@ class BaseOsmMap:
138
342
 
139
343
 
140
344
  def add_tile_layer(self):
345
+ """
346
+ Adds a tile layer to the OpenStreetMap (OSM) representation.
347
+ This method is intended to handle the inclusion of additional
348
+ tile layers in the map. Subclasses should override this method,
349
+ call their custom logic, and conclude with a call to this base
350
+ implementation to add necessary controls to the map instance.
351
+
352
+ :rtype: None
353
+ :return: This method does not return any value.
354
+ """
141
355
  # Override in subclass and call super().add_tile_layer at the end
142
356
  folium.LayerControl().add_to(self.osm_map)
143
357
 
144
358
 
145
359
  def _add_fullscreen(self):
360
+ """
361
+ Adds a fullscreen functionality to the map if the fullscreen attribute is set.
362
+
363
+ This method checks whether the fullscreen mode is enabled by evaluating
364
+ the `fullscreen` attribute of the class. If `fullscreen` is set to True,
365
+ a Fullscreen instance is created with the specified position from
366
+ `fullscreen_position` and added to the map (`osm_map`).
367
+
368
+ :return: None
369
+ """
146
370
  if self.fullscreen:
147
371
  Fullscreen(position=self.fullscreen_position).add_to(self.osm_map)
148
372
 
149
373
 
150
374
  def _add_map_title(self):
375
+ """
376
+ Adds a title to the map if the title is specified.
377
+
378
+ This method checks if the attribute `map_html_title` is set. If it is,
379
+ it creates an HTML element containing the title and adds it to the
380
+ map's root HTML structure using Folium's API.
381
+
382
+ :raises AttributeError: If `osm_map` or `osm_map.get_root()` is not defined
383
+ or does not support the necessary operations.
384
+ """
151
385
  if self.map_html_title:
152
386
  self.osm_map.get_root().html.add_child(folium.Element(self.map_html_title))
153
387
 
154
388
 
155
389
  @staticmethod
156
390
  def _sanitize_html(input_html):
391
+ """
392
+ Sanitizes the provided HTML input by escaping special HTML characters.
393
+ This method ensures the input string is safe for use in HTML contexts
394
+ by converting characters like `<`, `>`, and `&` into their corresponding
395
+ HTML-safe representations.
396
+
397
+ :param input_html: The HTML string that needs to be sanitized.
398
+ :type input_html: str
399
+ :return: The sanitized version of the input HTML string with special
400
+ characters escaped.
401
+ :rtype: str
402
+ """
157
403
  return html.escape(input_html)
158
404
 
159
405
 
160
406
  def generate_map(self):
407
+ """
408
+ Generates a map by executing preprocessing, main processing, and
409
+ post-processing tasks sequentially. This method combines multiple
410
+ stages to prepare and retrieve the final map object.
411
+
412
+ :return: The completed and processed OpenStreetMap map instance
413
+ :rtype: object
414
+ """
161
415
  self.pre_process_map()
162
416
  self.process_map()
163
417
  self._post_process_map()
@@ -23,6 +23,37 @@ from geopy.distance import geodesic
23
23
 
24
24
 
25
25
  class PBFHandler:
26
+ """
27
+ Handles the creation, management, and visualization of graph data derived
28
+ from .pbf (Protocolbuffer Binary Format) files. This class enables the
29
+ loading, processing, saving, and reutilization of graph, node, and edge
30
+ data for geographical regions, supporting verbose mode for detailed outputs.
31
+
32
+ :ivar graph: The generated graph object representing the spatial network; can be None if not yet loaded or processed.
33
+ :type graph: Optional[NetworkX.Graph]
34
+ :ivar nodes: GeoDataFrame representing the nodes of the graph; can be None if not yet loaded or processed.
35
+ :type nodes: Optional[geopandas.GeoDataFrame]
36
+ :ivar edges: GeoDataFrame representing the edges of the graph; can be None if not yet loaded or processed.
37
+ :type edges: Optional[geopandas.GeoDataFrame]
38
+ :ivar rebuild: Indicates whether to rebuild the graph data, ignoring any existing cached files. Default is ``False``.
39
+ :type rebuild: bool
40
+ :ivar verbose: Enables verbose mode to provide detailed status messages during operations. Default is ``False``.
41
+ :type verbose: bool
42
+ :ivar place: The name of the geographical region to process with OpenStreetMap. Default is ``Costa Rica``.
43
+ :type place: str
44
+ :ivar filepath: The path to the directory where the graph, nodes, and edges pickle files are saved. Default is ``gis_data/``.
45
+ :type filepath: str
46
+ :ivar file_prefix: The prefix for the filenames of the saved graph, node, and edge pickle files. Default is ``costa-rica-``.
47
+ :type file_prefix: str
48
+ :ivar network_type: The type of network to extract from OpenStreetMap, such as "all" or other specific network types. Default is ``all``.
49
+ :type network_type: str
50
+ :ivar graph_file: Full path of the file to save or load the graph data as a pickle file.
51
+ :type graph_file: str
52
+ :ivar node_file: Full path of the file to save or load the graph's node data as a pickle file.
53
+ :type node_file: str
54
+ :ivar edge_file: Full path of the file to save or load the graph's edge data as a pickle file.
55
+ :type edge_file: str
56
+ """
26
57
  def __init__(self, **kwargs):
27
58
  self.graph = None
28
59
  self.nodes = None
@@ -38,6 +69,23 @@ class PBFHandler:
38
69
  self.edge_file = f"{self.filepath}{self.file_prefix}edges.pkl"
39
70
 
40
71
  def load(self):
72
+ """
73
+ Loads the required data files for processing. If the files do not exist or
74
+ if the `rebuild` flag is set to True, it will process and recreate the
75
+ necessary data from the source. Otherwise, it will load the data from
76
+ existing pickle files. This function ensures the target directory exists,
77
+ and processes files conditionally based on their presence.
78
+
79
+ :param verbose: Flag to control the verbosity of the function's output.
80
+ :param rebuild: Indicates whether the data should be rebuilt from the raw
81
+ source files.
82
+ :param graph_file: Path to the graph file to be loaded or rebuilt.
83
+ :param node_file: Path to the node file to be loaded or rebuilt.
84
+ :param edge_file: Path to the edge file to be loaded or rebuilt.
85
+ :param filepath: Path to the directory where files are processed and saved.
86
+
87
+ :return: None
88
+ """
41
89
  if self.verbose:
42
90
  print("Loading data...")
43
91
 
@@ -62,7 +110,31 @@ class PBFHandler:
62
110
 
63
111
  def process_pbf(self):
64
112
  """
65
- Load a PBF file and create a graph.
113
+ Processes the Protocolbuffer Binary Format (PBF) data specified for a given place by
114
+ utilizing the OSMnx library to create a graph representation and extracts nodes and
115
+ edges into GeoDataFrames. The function provides verbose output if enabled.
116
+
117
+ :param self: Refers to the current instance of the class containing this method.
118
+
119
+ :param self.verbose: bool
120
+ A flag to control verbose output. If True, detailed processing status messages are
121
+ logged to the console.
122
+
123
+ :param self.place: str
124
+ The name or description of the geographic place for which PBF data is processed. It
125
+ is used to construct a graph representation of the place.
126
+
127
+ :param self.network_type: str
128
+ The type of network graph to be created, typically one of 'all', 'walk', 'drive',
129
+ etc., reflecting the type of paths or streets included in the graph.
130
+
131
+ :return: None
132
+ This function does not return a value, but updates class attributes ``graph``,
133
+ ``nodes``, and ``edges``.
134
+
135
+ :raises Exception:
136
+ Raises a general exception when there is an error in processing the PBF data. Error
137
+ details are printed when verbose output is enabled.
66
138
  """
67
139
  try:
68
140
  if self.verbose:
@@ -79,7 +151,20 @@ class PBFHandler:
79
151
 
80
152
  def save_to_pickle(self):
81
153
  """
82
- Save the graph, nodes, and edges to pickle files.
154
+ Saves data, including graph, nodes, and edges, to pickle files. Each data object is
155
+ saved to its corresponding file if available. If verbose mode is enabled, prints
156
+ messages indicating the saving progress and success.
157
+
158
+ :param self:
159
+ Represents the instance of the class that contains attributes `graph_file`,
160
+ `graph`, `node_file`, `nodes`, `edge_file`, `edges`, and `verbose`. These
161
+ attributes determine the files to save to and the data to save.
162
+
163
+ :raises Exception:
164
+ Raises an exception if an error occurs during the saving process.
165
+
166
+ :return:
167
+ None
83
168
  """
84
169
  try:
85
170
  if self.verbose:
@@ -104,7 +189,13 @@ class PBFHandler:
104
189
 
105
190
  def load_from_pickle(self):
106
191
  """
107
- Load the graph, nodes, and edges from pickle files.
192
+ Loads data from pickle files specified by the attributes `graph_file`, `node_file`,
193
+ and `edge_file` and assigns them to the corresponding attributes `graph`,
194
+ `nodes`, and `edges`, respectively. Displays verbose messages during the load
195
+ process if the `verbose` attribute is set to True.
196
+
197
+ :raises Exception: If an error occurs during reading or deserialization of the
198
+ pickle files.
108
199
  """
109
200
  try:
110
201
  if self.verbose:
@@ -128,7 +219,13 @@ class PBFHandler:
128
219
 
129
220
  def plot_graph(self):
130
221
  """
131
- Plot the graph.
222
+ Plots the loaded graph using the OSMnx library.
223
+
224
+ This method checks if a graph is loaded and, if available, plots it. Outputs
225
+ verbose messages during the process if verbosity is enabled.
226
+
227
+ :raises Exception: Raises if an error occurs during the plotting process.
228
+ :return: None
132
229
  """
133
230
  try:
134
231
  if self.graph is not None:
@@ -145,6 +242,23 @@ class PBFHandler:
145
242
 
146
243
 
147
244
  def get_bounding_box_from_points(gps_points, margin=0.001):
245
+ """
246
+ Calculates a bounding box from a list of GPS points, with an optional margin added
247
+ to expand the bounding box in all directions. The function iterates over the GPS
248
+ points to determine the maximum and minimum latitude and longitude values, then
249
+ applies the specified margin to calculate the bounding box's boundaries.
250
+
251
+ :param gps_points: A list of GPS points, where each point is represented as a tuple
252
+ containing a latitude and a longitude (latitude, longitude).
253
+ :type gps_points: list[tuple[float, float]]
254
+ :param margin: An optional margin value to expand the bounding box in all directions.
255
+ Default value is 0.001.
256
+ :type margin: float
257
+ :return: A tuple containing the bounding box boundaries in the following order:
258
+ north (maximum latitude), south (minimum latitude), east (maximum longitude),
259
+ and west (minimum longitude), each adjusted with the margin.
260
+ :rtype: tuple[float, float, float, float]
261
+ """
148
262
  latitudes = [point[0] for point in gps_points]
149
263
  longitudes = [point[1] for point in gps_points]
150
264
 
@@ -157,6 +271,28 @@ def get_bounding_box_from_points(gps_points, margin=0.001):
157
271
 
158
272
 
159
273
  def add_arrows(map_object, locations, color, n_arrows):
274
+ """
275
+ Adds directional arrows to a map object to indicate paths or flows along a polyline
276
+ defined by the given locations.
277
+
278
+ The function computes directional arrows based on the locations list, places them
279
+ along the defined path at intervals determined by the number of arrows, and adds
280
+ these arrows to the specified `map_object`.
281
+
282
+ .. note::
283
+ The function works optimally when the number of locations is greater than two.
284
+
285
+ :param map_object: The folium map object to which the directional arrows will be added.
286
+ :param locations: A list containing tuples of latitude and longitude values that define
287
+ the polyline. Each tuple represents a geographic point.
288
+ :type locations: list[tuple[float, float]]
289
+ :param color: The color to be used for the directional arrows.
290
+ :type color: str
291
+ :param n_arrows: The number of arrows to be drawn along the path.
292
+ :type n_arrows: int
293
+ :return: The modified folium map object containing the added arrows.
294
+ :rtype: folium.Map
295
+ """
160
296
  # Get the number of locations
161
297
  n = len(locations)
162
298
 
@@ -179,6 +315,26 @@ def add_arrows(map_object, locations, color, n_arrows):
179
315
 
180
316
 
181
317
  def extract_subgraph(G, north, south, east, west):
318
+ """
319
+ Extracts a subgraph from the input graph `G` within a specified bounding box. The bounding
320
+ box is defined by its north, south, east, and west coordinates. The function identifies
321
+ nodes from the graph that lie within this bounding box and creates a subgraph containing
322
+ only these nodes and their corresponding edges.
323
+
324
+ :param G: The input graph representing the original main graph.
325
+ :type G: networkx.Graph
326
+ :param north: The northern latitude that defines the upper boundary of the bounding box.
327
+ :type north: float
328
+ :param south: The southern latitude that defines the lower boundary of the bounding box.
329
+ :type south: float
330
+ :param east: The eastern longitude that defines the right boundary of the bounding box.
331
+ :type east: float
332
+ :param west: The western longitude that defines the left boundary of the bounding box.
333
+ :type west: float
334
+ :return: A subgraph extracted from the input graph `G` containing nodes and edges within
335
+ the specified bounding box.
336
+ :rtype: networkx.Graph
337
+ """
182
338
  # Create a bounding box polygon
183
339
  # from osmnx v2 this is how it is done
184
340
  if ox.__version__ >= '2.0':
@@ -199,6 +355,26 @@ def extract_subgraph(G, north, south, east, west):
199
355
 
200
356
 
201
357
  def get_distance_between_points(point_a, point_b, unit='km'):
358
+ """
359
+ Calculate the geographical distance between two points on Earth.
360
+
361
+ This function computes the distance between two points on the Earth's surface
362
+ specified in their geographical coordinates (latitude, longitude). The calculation
363
+ employs the geodesic distance, which represents the shortest distance between
364
+ two points on the Earth's surface. The distance can be returned in different units of
365
+ measurement depending on the provided parameter.
366
+
367
+ :param point_a: A tuple representing the latitude and longitude of the first
368
+ point in decimal degrees (e.g., (latitude, longitude)). Must be a tuple of
369
+ two float values.
370
+ :param point_b: A tuple representing the latitude and longitude of the second
371
+ point in decimal degrees (e.g., (latitude, longitude)). Must be a tuple of
372
+ two float values.
373
+ :param unit: A string value representing the unit of the calculated distance. Can be
374
+ 'km' for kilometers (default), 'm' for meters, or 'mi' for miles.
375
+ :return: A float value of the distance between the two points in the specified unit.
376
+ Returns 0 if the input validation fails or the specified unit is invalid.
377
+ """
202
378
  if not isinstance(point_a, tuple) or len(point_a) != 2:
203
379
  return 0
204
380
  if not all(isinstance(x, float) and not math.isnan(x) for x in point_a):
@@ -226,6 +402,20 @@ tile_options = {
226
402
 
227
403
 
228
404
  def attach_supported_tiles(map_object, default_tile="OpenStreetMap"):
405
+ """
406
+ Attaches supported tile layers to a given folium map object, excluding the
407
+ default tile layer, to provide layer selection functionality in the map.
408
+
409
+ This function allows dynamic addition of multiple tile layers to the map
410
+ object while avoiding duplication of the default tile. By filtering out the
411
+ default tile, it prevents redundancy and ensures a cleaner map interface.
412
+
413
+ :param map_object: The folium map object to which the tile layers will be added.
414
+ It must be an instance of Folium's Map class or a compatible map object.
415
+ :param default_tile: The name of the default tile layer to exclude from the
416
+ list of tiles added to the map. If not specified, defaults to 'OpenStreetMap'.
417
+ :return: None. The function modifies the provided map object in place.
418
+ """
229
419
  # Normalize the default tile name to lowercase for comparison
230
420
  normalized_default_tile = default_tile.lower()
231
421
 
@@ -237,12 +427,44 @@ def attach_supported_tiles(map_object, default_tile="OpenStreetMap"):
237
427
 
238
428
 
239
429
  def get_graph(**options):
430
+ """
431
+ Generates and returns a graph along with its nodes and edges based on the
432
+ provided options. The function initializes a PBFHandler instance with the
433
+ given options, processes any data required, and retrieves the resulting
434
+ graph structure.
435
+
436
+ :param options: Variable-length keyword arguments passed to initialize the
437
+ PBFHandler instance. These parameters play a role in
438
+ determining how the graph data is processed and structured.
439
+ :return: Returns a tuple containing three elements:
440
+ - The generated graph object
441
+ - The list or collection of nodes within the graph
442
+ - The list or collection of edges that describe relationships
443
+ between nodes in the graph
444
+ """
240
445
  handler = PBFHandler(**options)
241
446
  handler.load()
242
447
  return handler.graph, handler.nodes, handler.edges
243
448
 
244
449
 
245
450
  def add_query_params(url, params):
451
+ """
452
+ Update the query parameters of a given URL with new parameters.
453
+
454
+ This function takes a URL and a dictionary of parameters, merges these
455
+ parameters with the existing parameters in the URL, and returns a new URL
456
+ with updated query parameters.
457
+
458
+ :param url: The original URL whose query parameters are to be updated,
459
+ including the scheme, netloc, path, and optional query string and fragment.
460
+ :type url: str
461
+ :param params: A dictionary containing the new parameters to be added or updated
462
+ in the query string of the given URL.
463
+ :type params: dict
464
+ :return: A new URL with updated query parameters after merging the original
465
+ and new parameters.
466
+ :rtype: str
467
+ """
246
468
  # Parse the original URL
247
469
  url_components = urlsplit(url)
248
470