From 9b79e3eba0e84e99c524fecc4e4d2c22bd1661a3 Mon Sep 17 00:00:00 2001 From: marceloprates Date: Sat, 17 May 2025 01:15:53 +0000 Subject: [PATCH] deploy: d2bbf1083a705ccea0b912981596cf610a52c0ec --- api/index.html | 5800 +------------------------------------- index.html | 120 +- objects.inv | Bin 456 -> 132 bytes search/search_index.json | 2 +- usage/index.html | 171 +- 5 files changed, 8 insertions(+), 6085 deletions(-) diff --git a/api/index.html b/api/index.html index 45dfd85..3f8ef0f 100644 --- a/api/index.html +++ b/api/index.html @@ -257,19 +257,6 @@ - - @@ -282,355 +269,6 @@ - - - - @@ -655,344 +293,6 @@ - - - @@ -1008,5104 +308,8 @@

API Reference

-

This page documents the main modules and functions of the prettymaps library. The API documentation is auto-generated from the code and includes all public classes and functions.

-

Modules

- -
- - -
- - - -

- prettymaps.draw - - -

- -
- -

Prettymaps - A minimal Python library to draw pretty maps from OpenStreetMap Data -Copyright (C) 2021 Marcelo Prates

-

This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published -by the Free Software Foundation, either version 3 of the License, or -(at your option) any later version.

-

This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details.

-

You should have received a copy of the GNU Affero General Public License -along with this program. If not, see https://www.gnu.org/licenses/.

- - - - - - - - - -
- - - - - - - - -
- - - -

- Plot - - - - dataclass - - -

- - -
- - -

Dataclass implementing a prettymaps Plot object.

- - -

Attributes:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
geodataframes - Dict[str, GeoDataFrame] - -
-

A dictionary of GeoDataFrames (one for each plot layer).

-
-
fig - Figure - -
-

A matplotlib figure.

-
-
ax - Axes - -
-

A matplotlib axis object.

-
-
background - BaseGeometry - -
-

Background layer (shapely object).

-
-
keypoints - GeoDataFrame - -
-

Keypoints GeoDataFrame.

-
-
- - - - - - - -
- Source code in prettymaps/draw.py -
 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
@dataclass
-class Plot:
-    """
-    Dataclass implementing a prettymaps Plot object.
-
-    Attributes:
-        geodataframes (Dict[str, gp.GeoDataFrame]): A dictionary of GeoDataFrames (one for each plot layer).
-        fig (matplotlib.figure.Figure): A matplotlib figure.
-        ax (matplotlib.axes.Axes): A matplotlib axis object.
-        background (BaseGeometry): Background layer (shapely object).
-        keypoints (gp.GeoDataFrame): Keypoints GeoDataFrame.
-    """
-
-    geodataframes: Dict[str, gp.GeoDataFrame]
-    fig: matplotlib.figure.Figure
-    ax: matplotlib.axes.Axes
-    background: BaseGeometry
-    keypoints: gp.GeoDataFrame
-
-
- - - -
- - - - - - - - - - - -
- -
- -
- -
- - - -

- PolygonPatch - - -

- - -
-

- Bases: PathPatch

- - -

A class to create a matplotlib PathPatch from a shapely geometry.

- - -

Attributes:

- - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
shape - BaseGeometry - -
-

Shapely geometry.

-
-
kwargs - BaseGeometry - -
-

Parameters for matplotlib's PathPatch constructor.

-
-
- - -

Methods:

- - - - - - - - - - - - - -
NameDescription
__init__ -
-

BaseGeometry, **kwargs): -Initialize the PolygonPatch with the given shapely geometry and additional parameters.

-

shape (BaseGeometry): Shapely geometry. -kwargs: Parameters for matplotlib's PathPatch constructor.

-
-
- - - - - - - -
- Source code in prettymaps/draw.py -
115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
class PolygonPatch(PathPatch):
-    """
-    A class to create a matplotlib PathPatch from a shapely geometry.
-
-    Attributes:
-        shape (BaseGeometry): Shapely geometry.
-        kwargs: Parameters for matplotlib's PathPatch constructor.
-
-    Methods:
-        __init__(shape: BaseGeometry, **kwargs):
-            Initialize the PolygonPatch with the given shapely geometry and additional parameters.
-
-
-            shape (BaseGeometry): Shapely geometry.
-            kwargs: Parameters for matplotlib's PathPatch constructor.
-    """
-
-    def __init__(self, shape: BaseGeometry, **kwargs):
-        """
-        Initialize the PolygonPatch.
-
-        Args:
-            shape (BaseGeometry): Shapely geometry
-            kwargs: parameters for matplotlib's PathPatch constructor
-        """
-        # Init vertices and codes lists
-        vertices, codes = [], []
-        for geom in shape.geoms if hasattr(shape, "geoms") else [shape]:
-            for poly in geom.geoms if hasattr(geom, "geoms") else [geom]:
-                if type(poly) != Polygon:
-                    continue
-                # Get polygon's exterior and interiors
-                exterior = np.array(poly.exterior.xy)
-                interiors = [np.array(interior.xy) for interior in poly.interiors]
-                # Append to vertices and codes lists
-                vertices += [exterior] + interiors
-                codes += list(
-                    map(
-                        # Ring coding
-                        lambda p: [Path.MOVETO]
-                        + [Path.LINETO] * (p.shape[1] - 2)
-                        + [Path.CLOSEPOLY],
-                        [exterior] + interiors,
-                    )
-                )
-        # Initialize PathPatch with the generated Path
-        super().__init__(
-            Path(np.concatenate(vertices, 1).T, np.concatenate(codes)), **kwargs
-        )
-
-
- - - -
- - - - - - - - - -
- - -

- __init__(shape, **kwargs) - -

- - -
- -

Initialize the PolygonPatch.

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- shape - - BaseGeometry - -
-

Shapely geometry

-
-
- required -
- kwargs - - -
-

parameters for matplotlib's PathPatch constructor

-
-
- {} -
- - -
- Source code in prettymaps/draw.py -
132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
def __init__(self, shape: BaseGeometry, **kwargs):
-    """
-    Initialize the PolygonPatch.
-
-    Args:
-        shape (BaseGeometry): Shapely geometry
-        kwargs: parameters for matplotlib's PathPatch constructor
-    """
-    # Init vertices and codes lists
-    vertices, codes = [], []
-    for geom in shape.geoms if hasattr(shape, "geoms") else [shape]:
-        for poly in geom.geoms if hasattr(geom, "geoms") else [geom]:
-            if type(poly) != Polygon:
-                continue
-            # Get polygon's exterior and interiors
-            exterior = np.array(poly.exterior.xy)
-            interiors = [np.array(interior.xy) for interior in poly.interiors]
-            # Append to vertices and codes lists
-            vertices += [exterior] + interiors
-            codes += list(
-                map(
-                    # Ring coding
-                    lambda p: [Path.MOVETO]
-                    + [Path.LINETO] * (p.shape[1] - 2)
-                    + [Path.CLOSEPOLY],
-                    [exterior] + interiors,
-                )
-            )
-    # Initialize PathPatch with the generated Path
-    super().__init__(
-        Path(np.concatenate(vertices, 1).T, np.concatenate(codes)), **kwargs
-    )
-
-
-
- -
- - - -
- -
- -
- -
- - - -

- Preset - - - - dataclass - - -

- - -
- - -

Dataclass implementing a prettymaps Preset object.

- - -

Attributes:

- - - - - - - - - - - - - - - -
NameTypeDescription
params - dict - -
-

Dictionary of prettymaps.plot() parameters.

-
-
- - - - - - - -
- Source code in prettymaps/draw.py -
103
-104
-105
-106
-107
-108
-109
-110
-111
-112
@dataclass
-class Preset:
-    """
-    Dataclass implementing a prettymaps Preset object.
-
-    Attributes:
-        params (dict): Dictionary of prettymaps.plot() parameters.
-    """
-
-    params: dict
-
-
- - - -
- - - - - - - - - - - -
- -
- -
- -
- - - -

- Subplot - - -

- - -
- - -

Class implementing a prettymaps Subplot. Attributes: -- query: prettymaps.plot() query -- kwargs: dictionary of prettymaps.plot() parameters

- - - - - - - -
- Source code in prettymaps/draw.py -
71
-72
-73
-74
-75
-76
-77
-78
-79
-80
class Subplot:
-    """
-    Class implementing a prettymaps Subplot. Attributes:
-    - query: prettymaps.plot() query
-    - kwargs: dictionary of prettymaps.plot() parameters
-    """
-
-    def __init__(self, query, **kwargs):
-        self.query = query
-        self.kwargs = kwargs
-
-
- - - -
- - - - - - - - - - - -
- -
- -
- - -
- - -

- create_background(gdfs, style, logging=False) - -

- - -
- -

Create a background layer given a collection of GeoDataFrames

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- gdfs - - Dict[str, GeoDataFrame] - -
-

Dictionary of GeoDataFrames

-
-
- required -
- style - - Dict[str, dict] - -
-

Dictionary of matplotlib style parameters

-
-
- required -
- - -

Returns:

- - - - - - - - - - - - - -
TypeDescription
- Tuple[BaseGeometry, float, float, float, float, float, float] - -
-

Tuple[BaseGeometry, float, float, float, float, float, float]: background geometry, bounds, width and height

-
-
- - -
- Source code in prettymaps/draw.py -
580
-581
-582
-583
-584
-585
-586
-587
-588
-589
-590
-591
-592
-593
-594
-595
-596
-597
-598
-599
-600
-601
-602
-603
-604
-605
-606
-607
-608
-609
-610
-611
-612
-613
-614
-615
-616
-617
@log_execution_time
-def create_background(
-    gdfs: Dict[str, gp.GeoDataFrame],
-    style: Dict[str, dict],
-    logging=False,
-) -> Tuple[BaseGeometry, float, float, float, float, float, float]:
-    """
-    Create a background layer given a collection of GeoDataFrames
-
-    Args:
-        gdfs (Dict[str, gp.GeoDataFrame]): Dictionary of GeoDataFrames
-        style (Dict[str, dict]): Dictionary of matplotlib style parameters
-
-    Returns:
-        Tuple[BaseGeometry, float, float, float, float, float, float]: background geometry, bounds, width and height
-    """
-
-    # Create background
-    background_pad = 1.1
-    if "background" in style and "pad" in style["background"]:
-        background_pad = style["background"].pop("pad")
-
-    background = shapely.affinity.scale(
-        box(
-            *shapely.ops.unary_union(ox.project_gdf(gdfs["perimeter"]).geometry).bounds
-        ),
-        background_pad,
-        background_pad,
-    )
-
-    if "background" in style and "dilate" in style["background"]:
-        background = background.buffer(style["background"].pop("dilate"))
-
-    # Get bounds
-    xmin, ymin, xmax, ymax = background.bounds
-    dx, dy = xmax - xmin, ymax - ymin
-
-    return background, xmin, ymin, xmax, ymax, dx, dy
-
-
-
- -
- -
- - -

- create_preset(name, layers=None, style=None, circle=None, radius=None, dilate=None) - -

- - -
- -

Create a preset file and save it on the presets folder (prettymaps/presets/) under name 'name.json'

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- name - - str - -
-

Preset name

-
-
- required -
- layers - - Dict[str, dict] - -
-

prettymaps.plot() 'layers' parameter dict. Defaults to None.

-
-
- None -
- style - - Dict[str, dict] - -
-

prettymaps.plot() 'style' parameter dict. Defaults to None.

-
-
- None -
- circle - - Optional[bool] - -
-

prettymaps.plot() 'circle' parameter. Defaults to None.

-
-
- None -
- radius - - Optional[Union[float, bool]] - -
-

prettymaps.plot() 'radius' parameter. Defaults to None.

-
-
- None -
- dilate - - Optional[Union[float, bool]] - -
-

prettymaps.plot() 'dilate' parameter. Defaults to None.

-
-
- None -
- - -
- Source code in prettymaps/draw.py -
710
-711
-712
-713
-714
-715
-716
-717
-718
-719
-720
-721
-722
-723
-724
-725
-726
-727
-728
-729
-730
-731
-732
-733
-734
-735
-736
-737
-738
-739
-740
-741
-742
-743
-744
-745
def create_preset(
-    name: str,
-    layers: Optional[Dict[str, dict]] = None,
-    style: Optional[Dict[str, dict]] = None,
-    circle: Optional[bool] = None,
-    radius: Optional[Union[float, bool]] = None,
-    dilate: Optional[Union[float, bool]] = None,
-) -> None:
-    """
-    Create a preset file and save it on the presets folder (prettymaps/presets/) under name 'name.json'
-
-    Args:
-        name (str): Preset name
-        layers (Dict[str, dict], optional): prettymaps.plot() 'layers' parameter dict. Defaults to None.
-        style (Dict[str, dict], optional): prettymaps.plot() 'style' parameter dict. Defaults to None.
-        circle (Optional[bool], optional): prettymaps.plot() 'circle' parameter. Defaults to None.
-        radius (Optional[Union[float, bool]], optional): prettymaps.plot() 'radius' parameter. Defaults to None.
-        dilate (Optional[Union[float, bool]], optional): prettymaps.plot() 'dilate' parameter. Defaults to None.
-    """
-
-    # if not os.path.isdir('presets'):
-    #    os.makedirs('presets')
-
-    path = os.path.join(presets_directory(), f"{name}.json")
-    with open(path, "w") as f:
-        json.dump(
-            {
-                "layers": layers,
-                "style": style,
-                "circle": circle,
-                "radius": radius,
-                "dilate": dilate,
-            },
-            f,
-            ensure_ascii=False,
-        )
-
-
-
- -
- -
- - -

- draw_credit(ax, background, credit, mode, multiplot, logging=False) - -

- - -
- -

Draws credit text on the plot.

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- ax - - Axes - -
-

Matplotlib axis object.

-
-
- required -
- background - - BaseGeometry - -
-

Background layer.

-
-
- required -
- credit - - Dict[str, Any] - -
-

Dictionary containing credit text and style parameters.

-
-
- required -
- mode - - str - -
-

Drawing mode. Options: 'matplotlib', 'plotter'.

-
-
- required -
- multiplot - - bool - -
-

Whether the plot is part of a multiplot.

-
-
- required -
- logging - - bool - -
-

Whether to enable logging. Defaults to False.

-
-
- False -
- - -
- Source code in prettymaps/draw.py -
946
-947
-948
-949
-950
-951
-952
-953
-954
-955
-956
-957
-958
-959
-960
-961
-962
-963
-964
-965
-966
-967
@log_execution_time
-def draw_credit(
-    ax: matplotlib.axes.Axes,
-    background: BaseGeometry,
-    credit: Dict[str, Any],
-    mode: str,
-    multiplot: bool,
-    logging: bool = False,
-) -> None:
-    """
-    Draws credit text on the plot.
-
-    Args:
-        ax (matplotlib.axes.Axes): Matplotlib axis object.
-        background (BaseGeometry): Background layer.
-        credit (Dict[str, Any]): Dictionary containing credit text and style parameters.
-        mode (str): Drawing mode. Options: 'matplotlib', 'plotter'.
-        multiplot (bool): Whether the plot is part of a multiplot.
-        logging (bool, optional): Whether to enable logging. Defaults to False.
-    """
-    if (mode == "matplotlib") and (credit != False) and (not multiplot):
-        draw_text(ax, credit, background)
-
-
-
- -
- -
- - -

- draw_text(ax, params, background) - -

- - -
- -

Draw text with content and matplotlib style parameters specified by 'params' dictionary. -params['text'] should contain the message to be drawn.

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- ax - - Axes - -
-

Matplotlib axis object.

-
-
- required -
- params - - Dict[str, Any] - -
-

Matplotlib style parameters for drawing text. params['text'] should contain the message to be drawn.

-
-
- required -
- background - - BaseGeometry - -
-

Background layer.

-
-
- required -
- - -
- Source code in prettymaps/draw.py -
905
-906
-907
-908
-909
-910
-911
-912
-913
-914
-915
-916
-917
-918
-919
-920
-921
-922
-923
-924
-925
-926
-927
-928
-929
-930
-931
-932
-933
-934
-935
-936
-937
-938
-939
-940
-941
-942
-943
def draw_text(
-    ax: matplotlib.axes.Axes, params: Dict[str, Any], background: BaseGeometry
-) -> None:
-    """
-    Draw text with content and matplotlib style parameters specified by 'params' dictionary.
-    params['text'] should contain the message to be drawn.
-
-    Args:
-        ax (matplotlib.axes.Axes): Matplotlib axis object.
-        params (Dict[str, Any]): Matplotlib style parameters for drawing text. params['text'] should contain the message to be drawn.
-        background (BaseGeometry): Background layer.
-    """
-    # Override default osm_credit dict with provided parameters
-    params = override_params(
-        dict(
-            text="\n".join(
-                [
-                    "data © OpenStreetMap contributors",
-                    "github.com/marceloprates/prettymaps",
-                ]
-            ),
-            x=0,
-            y=1,
-            horizontalalignment="left",
-            verticalalignment="top",
-            bbox=dict(boxstyle="square", fc="#fff", ec="#000"),
-            # fontfamily="Ubuntu Mono",
-        ),
-        params,
-    )
-    x, y, text = [params.pop(k) for k in ["x", "y", "text"]]
-
-    # Get background bounds
-    xmin, ymin, xmax, ymax = background.bounds
-
-    x = np.interp([x], [0, 1], [xmin, xmax])[0]
-    y = np.interp([y], [0, 1], [ymin, ymax])[0]
-
-    ax.text(x, y, text, zorder=1000, **params)
-
-
-
- -
- -
- - -

- gdf_to_shapely(layer, gdf, width=None, point_size=None, line_width=None, **kwargs) - -

- - -
- -

Convert a dict of GeoDataFrames to a dict of shapely geometries

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- layer - - str - -
-

Layer name

-
-
- required -
- gdf - - GeoDataFrame - -
-

Input GeoDataFrame

-
-
- required -
- width - - Optional[Union[dict, float]] - -
-

Street network width. Can be either a dictionary or a float. Defaults to None.

-
-
- None -
- point_size - - Optional[float] - -
-

Point geometries (1D) will be dilated by this amount. Defaults to None.

-
-
- None -
- line_width - - Optional[float] - -
-

Line geometries (2D) will be dilated by this amount. Defaults to None.

-
-
- None -
- - -

Returns:

- - - - - - - - - - - - - -
Name TypeDescription
GeometryCollection - GeometryCollection - -
-

Output GeoDataFrame

-
-
- - -
- Source code in prettymaps/draw.py -
256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
def gdf_to_shapely(
-    layer: str,
-    gdf: gp.GeoDataFrame,
-    width: Optional[Union[dict, float]] = None,
-    point_size: Optional[float] = None,
-    line_width: Optional[float] = None,
-    **kwargs,
-) -> GeometryCollection:
-    """
-    Convert a dict of GeoDataFrames to a dict of shapely geometries
-
-    Args:
-        layer (str): Layer name
-        gdf (gp.GeoDataFrame): Input GeoDataFrame
-        width (Optional[Union[dict, float]], optional): Street network width. Can be either a dictionary or a float. Defaults to None.
-        point_size (Optional[float], optional): Point geometries (1D) will be dilated by this amount. Defaults to None.
-        line_width (Optional[float], optional): Line geometries (2D) will be dilated by this amount. Defaults to None.
-
-    Returns:
-        GeometryCollection: Output GeoDataFrame
-    """
-
-    # Project gdf if applicable
-    if not gdf.empty and gdf.crs is not None:
-        gdf = ox.project_gdf(gdf)
-
-    if layer in ["streets", "railway", "waterway"]:
-        geometries = graph_to_shapely(gdf, width)
-    else:
-        geometries = geometries_to_shapely(
-            gdf, point_size=point_size, line_width=line_width
-        )
-
-    return geometries
-
-
-
- -
- -
- - -

- geometries_to_shapely(gdf, point_size=None, line_width=None) - -

- - -
- -

Convert geometries in GeoDataFrame to shapely format

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- gdf - - GeoDataFrame - -
-

Input GeoDataFrame

-
-
- required -
- point_size - - Optional[float] - -
-

Point geometries (1D) will be dilated by this amount. Defaults to None.

-
-
- None -
- line_width - - Optional[float] - -
-

Line geometries (2D) will be dilated by this amount. Defaults to None.

-
-
- None -
- - -

Returns:

- - - - - - - - - - - - - -
Name TypeDescription
GeometryCollection - GeometryCollection - -
-

Shapely geometries computed from GeoDataFrame geometries

-
-
- - -
- Source code in prettymaps/draw.py -
215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
def geometries_to_shapely(
-    gdf: gp.GeoDataFrame,
-    point_size: Optional[float] = None,
-    line_width: Optional[float] = None,
-) -> GeometryCollection:
-    """
-    Convert geometries in GeoDataFrame to shapely format
-
-    Args:
-        gdf (gp.GeoDataFrame): Input GeoDataFrame
-        point_size (Optional[float], optional): Point geometries (1D) will be dilated by this amount. Defaults to None.
-        line_width (Optional[float], optional): Line geometries (2D) will be dilated by this amount. Defaults to None.
-
-    Returns:
-        GeometryCollection: Shapely geometries computed from GeoDataFrame geometries
-    """
-
-    geoms = gdf.geometry.tolist()
-    collections = [x for x in geoms if type(x) == GeometryCollection]
-    points = [x for x in geoms if type(x) == Point] + [
-        y for x in collections for y in x.geoms if type(y) == Point
-    ]
-    lines = [x for x in geoms if type(x) in [LineString, MultiLineString]] + [
-        y
-        for x in collections
-        for y in x.geoms
-        if type(y) in [LineString, MultiLineString]
-    ]
-    polys = [x for x in geoms if type(x) in [Polygon, MultiPolygon]] + [
-        y for x in collections for y in x.geoms if type(y) in [Polygon, MultiPolygon]
-    ]
-
-    # Convert points into circles with radius "point_size"
-    if point_size:
-        points = [x.buffer(point_size) for x in points] if point_size > 0 else []
-    if line_width:
-        lines = [x.buffer(line_width) for x in lines] if line_width > 0 else []
-
-    return GeometryCollection(list(points) + list(lines) + list(polys))
-
-
-
- -
- -
- - -

- graph_to_shapely(gdf, width=1.0) - -

- - -
- -

Given a GeoDataFrame containing a graph (street newtork), -convert them to shapely geometries by applying dilation given by 'width'

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- gdf - - GeoDataFrame - -
-

input GeoDataFrame containing graph (street network) geometries

-
-
- required -
- width - - float - -
-

Line geometries will be dilated by this amount. Defaults to 1..

-
-
- 1.0 -
- - -

Returns:

- - - - - - - - - - - - - -
Name TypeDescription
BaseGeometry - BaseGeometry - -
-

Shapely

-
-
- - -
- Source code in prettymaps/draw.py -
171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
def graph_to_shapely(gdf: gp.GeoDataFrame, width: float = 1.0) -> BaseGeometry:
-    """
-    Given a GeoDataFrame containing a graph (street newtork),
-    convert them to shapely geometries by applying dilation given by 'width'
-
-    Args:
-        gdf (gp.GeoDataFrame): input GeoDataFrame containing graph (street network) geometries
-        width (float, optional): Line geometries will be dilated by this amount. Defaults to 1..
-
-    Returns:
-        BaseGeometry: Shapely
-    """
-
-    def highway_to_width(highway):
-        if (type(highway) == str) and (highway in width):
-            return width[highway]
-        elif isinstance(highway, Iterable):
-            for h in highway:
-                if h in width:
-                    return width[h]
-            return np.nan
-        else:
-            return np.nan
-
-    # Annotate GeoDataFrame with the width for each highway type
-    gdf["width"] = (
-        gdf["highway"].map(highway_to_width) if type(width) == dict else width
-    )
-
-    # Remove rows with inexistent width
-    gdf.drop(gdf[gdf.width.isna()].index, inplace=True)
-
-    with warnings.catch_warnings():
-        # Supress shapely.errors.ShapelyDeprecationWarning
-        warnings.simplefilter("ignore", shapely.errors.ShapelyDeprecationWarning)
-        if not all(gdf.width.isna()):
-            # Dilate geometries based on their width
-            gdf.geometry = gdf.apply(
-                lambda row: row["geometry"].buffer(row.width), axis=1
-            )
-
-    return shapely.ops.unary_union(gdf.geometry)
-
-
-
- -
- -
- - -

- manage_presets(load_preset, save_preset, update_preset, layers, style, circle, radius, dilate, logging=False) - -

- - -
- -

summary

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- load_preset - - Optional[str] - -
-

Load preset named 'load_preset', if provided

-
-
- required -
- save_preset - - Optional[str] - -
-

Save preset to file named 'save_preset', if provided

-
-
- required -
- update_preset - - Optional[str] - -
-

Load, update and save preset named 'update_preset', if provided

-
-
- required -
- layers - - Dict[str, dict] - -
-

prettymaps.plot() 'layers' parameter dict

-
-
- required -
- style - - Dict[str, dict] - -
-

prettymaps.plot() 'style' parameter dict

-
-
- required -
- circle - - Optional[bool] - -
-

prettymaps.plot() 'circle' parameter

-
-
- required -
- radius - - Optional[Union[float, bool]] - -
-

prettymaps.plot() 'radius' parameter

-
-
- required -
- dilate - - Optional[Union[float, bool]] - -
-

prettymaps.plot() 'dilate' parameter

-
-
- required -
- - -

Returns:

- - - - - - - - - - - - - -
TypeDescription
- Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]] - -
-

Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]]: Updated layers, style, circle, radius, dilate parameters

-
-
- - -
- Source code in prettymaps/draw.py -
765
-766
-767
-768
-769
-770
-771
-772
-773
-774
-775
-776
-777
-778
-779
-780
-781
-782
-783
-784
-785
-786
-787
-788
-789
-790
-791
-792
-793
-794
-795
-796
-797
-798
-799
-800
-801
-802
-803
-804
-805
-806
-807
-808
-809
-810
-811
-812
-813
-814
-815
-816
-817
-818
-819
-820
-821
@log_execution_time
-def manage_presets(
-    load_preset: Optional[str],
-    save_preset: bool,
-    update_preset: Optional[str],
-    layers: Dict[str, dict],
-    style: Dict[str, dict],
-    circle: Optional[bool],
-    radius: Optional[Union[float, bool]],
-    dilate: Optional[Union[float, bool]],
-    logging=False,
-) -> Tuple[
-    dict,
-    dict,
-    Optional[float],
-    Optional[Union[float, bool]],
-    Optional[Union[float, bool]],
-]:
-    """_summary_
-
-    Args:
-        load_preset (Optional[str]): Load preset named 'load_preset', if provided
-        save_preset (Optional[str]): Save preset to file named 'save_preset', if provided
-        update_preset (Optional[str]): Load, update and save preset named 'update_preset', if provided
-        layers (Dict[str, dict]): prettymaps.plot() 'layers' parameter dict
-        style (Dict[str, dict]): prettymaps.plot() 'style' parameter dict
-        circle (Optional[bool]): prettymaps.plot() 'circle' parameter
-        radius (Optional[Union[float, bool]]): prettymaps.plot() 'radius' parameter
-        dilate (Optional[Union[float, bool]]): prettymaps.plot() 'dilate' parameter
-
-    Returns:
-        Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]]: Updated layers, style, circle, radius, dilate parameters
-    """
-
-    # Update preset mode: load a preset, update it with additional parameters and update the JSON file
-    if update_preset is not None:
-        # load_preset = save_preset = True
-        load_preset = save_preset = update_preset
-
-    # Load preset (if provided)
-    if load_preset is not None:
-        layers, style, circle, radius, dilate = override_preset(
-            load_preset, layers, style, circle, radius, dilate
-        )
-
-    # Save parameters as preset
-    if save_preset is not None:
-        create_preset(
-            save_preset,
-            layers=layers,
-            style=style,
-            circle=circle,
-            radius=radius,
-            dilate=dilate,
-        )
-
-    return layers, style, circle, radius, dilate
-
-
-
- -
- -
- - -

- multiplot(*subplots, figsize=None, credit={}, **kwargs) - -

- - -
- -

Creates a multiplot using the provided subplots and optional parameters.

-
Parameters:
-

subplots : list - A list of subplot objects to be plotted. -figsize : tuple, optional - A tuple specifying the figure size (width, height) in inches. -credit : dict, optional - A dictionary containing credit information for the plot. -*kwargs : dict, optional - Additional keyword arguments to customize the plot.

-
Returns:
-

None

- - -
- Source code in prettymaps/draw.py -
1253
-1254
-1255
-1256
-1257
-1258
-1259
-1260
-1261
-1262
-1263
-1264
-1265
-1266
-1267
-1268
-1269
-1270
-1271
-1272
-1273
-1274
-1275
-1276
-1277
-1278
-1279
-1280
-1281
-1282
-1283
-1284
-1285
-1286
-1287
-1288
-1289
-1290
-1291
-1292
-1293
-1294
-1295
-1296
-1297
-1298
-1299
def multiplot(*subplots, figsize=None, credit={}, **kwargs):
-    """
-    Creates a multiplot using the provided subplots and optional parameters.
-
-    Parameters:
-    -----------
-    *subplots : list
-        A list of subplot objects to be plotted.
-    figsize : tuple, optional
-        A tuple specifying the figure size (width, height) in inches.
-    credit : dict, optional
-        A dictionary containing credit information for the plot.
-    **kwargs : dict, optional
-        Additional keyword arguments to customize the plot.
-
-    Returns:
-    --------
-    None
-    """
-
-    fig = plt.figure(figsize=figsize)
-    ax = plt.subplot(111, aspect="equal")
-
-    mode = "plotter" if "plotter" in kwargs and kwargs["plotter"] else "matplotlib"
-
-    subplots_results = [
-        plot(
-            subplot.query,
-            ax=ax,
-            multiplot=True,
-            **override_params(
-                subplot.kwargs,
-                {
-                    k: v
-                    for k, v in kwargs.items()
-                    if k != "load_preset" or "load_preset" not in subplot.kwargs
-                },
-            ),
-            show=False,
-        )
-        for subplot in subplots
-    ]
-
-    if mode == "matplotlib":
-        ax.axis("off")
-        ax.axis("equal")
-        ax.autoscale()
-
-
-
- -
- -
- - -

- override_args(layers, circle, dilate, logging=False) - -

- - -
- -

Override arguments in layers' kwargs

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- layers - - dict - -
-

prettymaps.plot() Layers parameters dict

-
-
- required -
- circle - - Optional[bool] - -
-

prettymaps.plot() 'Circle' parameter

-
-
- required -
- dilate - - Optional[Union[float, bool]] - -
-

prettymaps.plot() 'dilate' parameter

-
-
- required -
- - -

Returns:

- - - - - - - - - - - - - -
Name TypeDescription
dict - dict - -
-

output dict

-
-
- - -
- Source code in prettymaps/draw.py -
1041
-1042
-1043
-1044
-1045
-1046
-1047
-1048
-1049
-1050
-1051
-1052
-1053
-1054
-1055
-1056
-1057
-1058
-1059
-1060
-1061
-1062
-1063
-1064
@log_execution_time
-def override_args(
-    layers: dict,
-    circle: Optional[bool],
-    dilate: Optional[Union[float, bool]],
-    logging=False,
-) -> dict:
-    """
-    Override arguments in layers' kwargs
-
-    Args:
-        layers (dict): prettymaps.plot() Layers parameters dict
-        circle (Optional[bool]): prettymaps.plot() 'Circle' parameter
-        dilate (Optional[Union[float, bool]]): prettymaps.plot() 'dilate' parameter
-
-    Returns:
-        dict: output dict
-    """
-    override_args = ["circle", "dilate"]
-    for layer in layers:
-        for arg in override_args:
-            if arg not in layers[layer]:
-                layers[layer][arg] = locals()[arg]
-    return layers
-
-
-
- -
- -
- - -

- override_params(default_dict, new_dict) - -

- - -
- -

Override parameters in 'default_dict' with additional parameters from 'new_dict'

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- default_dict - - dict - -
-

Default dict to be overriden with 'new_dict' parameters

-
-
- required -
- new_dict - - dict - -
-

New dict to override 'default_dict' parameters

-
-
- required -
- - -

Returns:

- - - - - - - - - - - - - -
Name TypeDescription
dict - dict - -
-

default_dict overriden with new_dict parameters

-
-
- - -
- Source code in prettymaps/draw.py -
1015
-1016
-1017
-1018
-1019
-1020
-1021
-1022
-1023
-1024
-1025
-1026
-1027
-1028
-1029
-1030
-1031
-1032
-1033
-1034
-1035
-1036
-1037
-1038
def override_params(default_dict: dict, new_dict: dict) -> dict:
-    """
-    Override parameters in 'default_dict' with additional parameters from 'new_dict'
-
-    Args:
-        default_dict (dict): Default dict to be overriden with 'new_dict' parameters
-        new_dict (dict): New dict to override 'default_dict' parameters
-
-    Returns:
-        dict: default_dict overriden with new_dict parameters
-    """
-
-    final_dict = deepcopy(default_dict)
-
-    for key in new_dict.keys():
-        if type(new_dict[key]) == dict:
-            if key in final_dict:
-                final_dict[key] = override_params(final_dict[key], new_dict[key])
-            else:
-                final_dict[key] = new_dict[key]
-        else:
-            final_dict[key] = new_dict[key]
-
-    return final_dict
-
-
-
- -
- -
- - -

- override_preset(name, layers={}, style={}, circle=None, radius=None, dilate=None) - -

- - -
- -

Read the preset file given by 'name' and override it with additional parameters

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- name - - str - -
-

description

-
-
- required -
- layers - - Dict[str, dict] - -
-

description. Defaults to {}.

-
-
- {} -
- style - - Dict[str, dict] - -
-

description. Defaults to {}.

-
-
- {} -
- circle - - Union[float, None] - -
-

description. Defaults to None.

-
-
- None -
- radius - - Union[float, None] - -
-

description. Defaults to None.

-
-
- None -
- dilate - - Union[float, None] - -
-

description. Defaults to None.

-
-
- None -
- - -

Returns:

- - - - - - - - - - - - - -
TypeDescription
- Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]] - -
-

Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]]: Preset parameters overriden by additional provided parameters

-
-
- - -
- Source code in prettymaps/draw.py -
849
-850
-851
-852
-853
-854
-855
-856
-857
-858
-859
-860
-861
-862
-863
-864
-865
-866
-867
-868
-869
-870
-871
-872
-873
-874
-875
-876
-877
-878
-879
-880
-881
-882
-883
-884
-885
-886
-887
-888
-889
-890
-891
-892
-893
-894
-895
-896
-897
def override_preset(
-    name: str,
-    layers: Dict[str, dict] = {},
-    style: Dict[str, dict] = {},
-    circle: Optional[float] = None,
-    radius: Optional[Union[float, bool]] = None,
-    dilate: Optional[Union[float, bool]] = None,
-) -> Tuple[
-    dict,
-    dict,
-    Optional[float],
-    Optional[Union[float, bool]],
-    Optional[Union[float, bool]],
-]:
-    """
-    Read the preset file given by 'name' and override it with additional parameters
-
-    Args:
-        name (str): _description_
-        layers (Dict[str, dict], optional): _description_. Defaults to {}.
-        style (Dict[str, dict], optional): _description_. Defaults to {}.
-        circle (Union[float, None], optional): _description_. Defaults to None.
-        radius (Union[float, None], optional): _description_. Defaults to None.
-        dilate (Union[float, None], optional): _description_. Defaults to None.
-
-    Returns:
-        Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]]: Preset parameters overriden by additional provided parameters
-    """
-
-    params = read_preset(name)
-
-    # Override preset with kwargs
-    if "layers" in params:
-        layers = override_params(params["layers"], layers)
-    if "style" in params:
-        style = override_params(params["style"], style)
-    if circle is None and "circle" in params:
-        circle = params["circle"]
-    if radius is None and "radius" in params:
-        radius = params["radius"]
-    if dilate is None and "dilate" in params:
-        dilate = params["dilate"]
-
-    # Delete layers marked as 'False' in the parameter dict
-    for layer in [key for key in layers.keys() if layers[key] == False]:
-        del layers[layer]
-
-    # Return overriden presets
-    return layers, style, circle, radius, dilate
-
-
-
- -
- -
- - -

- plot(query, layers={}, style={}, keypoints={}, preset='default', use_preset=True, save_preset=None, update_preset=None, postprocessing=lambda x: x, circle=None, radius=None, dilate=None, save_as=None, fig=None, ax=None, figsize=(11.7, 11.7), credit={}, mode='matplotlib', multiplot=False, show=True, x=0, y=0, scale_x=1, scale_y=1, rotation=0, logging=False, semantic=False, adjust_aspect_ratio=True) - -

- - -
- -

Plots a map based on a given query and specified parameters. -Args: - query: The query for the location to plot. This can be a string (e.g., "Porto Alegre"), a tuple of latitude and longitude coordinates, or a custom GeoDataFrame boundary. - layers: The OpenStreetMap layers to plot. Defaults to an empty dictionary. - style: Matplotlib parameters for drawing each layer. Defaults to an empty dictionary. - keypoints: Keypoints to highlight on the map. Defaults to an empty dictionary. - preset: Preset configuration to use. Defaults to "default". - use_preset: Whether to use the preset configuration. Defaults to True. - save_preset: Path to save the preset configuration. Defaults to None. - update_preset: Path to update the preset configuration with additional parameters. Defaults to None. - circle: Whether to use a circular boundary. Defaults to None. - radius: Radius for the circular or square boundary. Defaults to None. - dilate: Amount to dilate the boundary. Defaults to None. - save_as: Path to save the resulting plot. Defaults to None. - fig: Matplotlib figure object. Defaults to None. - ax: Matplotlib axes object. Defaults to None. - title: Title of the plot. Defaults to None. - figsize: Size of the figure. Defaults to (11.7, 11.7). - constrained_layout: Whether to use constrained layout for the figure. Defaults to True. - credit: Parameters for the credit message. Defaults to an empty dictionary. - mode: Mode for plotting ('matplotlib' or 'plotter'). Defaults to "matplotlib". - multiplot: Whether to use multiplot mode. Defaults to False. - show: Whether to display the plot using matplotlib. Defaults to True. - x: Translation parameter in the x direction. Defaults to 0. - y: Translation parameter in the y direction. Defaults to 0. - scale_x: Scaling parameter in the x direction. Defaults to 1. - scale_y: Scaling parameter in the y direction. Defaults to 1. - rotation: Rotation parameter in degrees. Defaults to 0. - logging: Whether to enable logging. Defaults to False. -Returns: - Plot: The resulting plot object.

- - -
- Source code in prettymaps/draw.py -
1102
-1103
-1104
-1105
-1106
-1107
-1108
-1109
-1110
-1111
-1112
-1113
-1114
-1115
-1116
-1117
-1118
-1119
-1120
-1121
-1122
-1123
-1124
-1125
-1126
-1127
-1128
-1129
-1130
-1131
-1132
-1133
-1134
-1135
-1136
-1137
-1138
-1139
-1140
-1141
-1142
-1143
-1144
-1145
-1146
-1147
-1148
-1149
-1150
-1151
-1152
-1153
-1154
-1155
-1156
-1157
-1158
-1159
-1160
-1161
-1162
-1163
-1164
-1165
-1166
-1167
-1168
-1169
-1170
-1171
-1172
-1173
-1174
-1175
-1176
-1177
-1178
-1179
-1180
-1181
-1182
-1183
-1184
-1185
-1186
-1187
-1188
-1189
-1190
-1191
-1192
-1193
-1194
-1195
-1196
-1197
-1198
-1199
-1200
-1201
-1202
-1203
-1204
-1205
-1206
-1207
-1208
-1209
-1210
-1211
-1212
-1213
-1214
-1215
-1216
-1217
-1218
-1219
-1220
-1221
-1222
-1223
-1224
-1225
-1226
-1227
-1228
-1229
-1230
-1231
-1232
-1233
-1234
-1235
-1236
-1237
-1238
-1239
-1240
-1241
-1242
-1243
-1244
-1245
-1246
-1247
-1248
-1249
-1250
def plot(
-    query: str | Tuple[float, float] | gp.GeoDataFrame,
-    layers: Dict[str, Dict[str, Any]] = {},
-    style: Dict[str, Dict[str, Any]] = {},
-    keypoints: Dict[str, Any] = {},
-    preset: str = "default",
-    use_preset: bool = True,
-    save_preset: str | None = None,
-    update_preset: str | None = None,
-    postprocessing: Callable[
-        [Dict[str, gp.GeoDataFrame]], Dict[str, gp.GeoDataFrame]
-    ] = lambda x: x,
-    circle: bool | None = None,
-    radius: float | bool | None = None,
-    dilate: float | bool | None = None,
-    save_as: str | None = None,
-    fig: plt.Figure | None = None,
-    ax: plt.Axes | None = None,
-    figsize: Tuple[float, float] = (11.7, 11.7),
-    credit: Dict[str, Any] = {},
-    mode: str = "matplotlib",
-    multiplot: bool = False,
-    show: bool = True,
-    x: float = 0,
-    y: float = 0,
-    scale_x: float = 1,
-    scale_y: float = 1,
-    rotation: float = 0,
-    logging: bool = False,
-    semantic: bool = False,
-    adjust_aspect_ratio: bool = True,
-) -> Plot:
-    """
-    Plots a map based on a given query and specified parameters.
-    Args:
-        query: The query for the location to plot. This can be a string (e.g., "Porto Alegre"), a tuple of latitude and longitude coordinates, or a custom GeoDataFrame boundary.
-        layers: The OpenStreetMap layers to plot. Defaults to an empty dictionary.
-        style: Matplotlib parameters for drawing each layer. Defaults to an empty dictionary.
-        keypoints: Keypoints to highlight on the map. Defaults to an empty dictionary.
-        preset: Preset configuration to use. Defaults to "default".
-        use_preset: Whether to use the preset configuration. Defaults to True.
-        save_preset: Path to save the preset configuration. Defaults to None.
-        update_preset: Path to update the preset configuration with additional parameters. Defaults to None.
-        circle: Whether to use a circular boundary. Defaults to None.
-        radius: Radius for the circular or square boundary. Defaults to None.
-        dilate: Amount to dilate the boundary. Defaults to None.
-        save_as: Path to save the resulting plot. Defaults to None.
-        fig: Matplotlib figure object. Defaults to None.
-        ax: Matplotlib axes object. Defaults to None.
-        title: Title of the plot. Defaults to None.
-        figsize: Size of the figure. Defaults to (11.7, 11.7).
-        constrained_layout: Whether to use constrained layout for the figure. Defaults to True.
-        credit: Parameters for the credit message. Defaults to an empty dictionary.
-        mode: Mode for plotting ('matplotlib' or 'plotter'). Defaults to "matplotlib".
-        multiplot: Whether to use multiplot mode. Defaults to False.
-        show: Whether to display the plot using matplotlib. Defaults to True.
-        x: Translation parameter in the x direction. Defaults to 0.
-        y: Translation parameter in the y direction. Defaults to 0.
-        scale_x: Scaling parameter in the x direction. Defaults to 1.
-        scale_y: Scaling parameter in the y direction. Defaults to 1.
-        rotation: Rotation parameter in degrees. Defaults to 0.
-        logging: Whether to enable logging. Defaults to False.
-    Returns:
-        Plot: The resulting plot object.
-    """
-
-    # 1. Manage presets
-    layers, style, circle, radius, dilate = manage_presets(
-        preset if use_preset else None,
-        save_preset,
-        update_preset,
-        layers,
-        style,
-        circle,
-        radius,
-        dilate,
-    )
-
-    # 2. Init matplotlib figure & axis and vsketch object
-    fig, ax, vsk = init_plot(
-        layers,
-        fig,
-        ax,
-        figsize,
-        mode,
-        adjust_aspect_ratio=adjust_aspect_ratio,
-        logging=logging,
-    )
-
-    # 3. Override arguments in layers' kwargs dict
-    layers = override_args(layers, circle, dilate, logging=logging)
-
-    # 4. Fetch geodataframes
-    start_time = time.time()
-    gdfs = get_gdfs(query, layers, radius, dilate, -rotation, logging=logging)
-    fetch_time = time.time() - start_time
-    print(f"Fetching geodataframes took {fetch_time:.2f} seconds")
-
-    # 5. Apply transformations to GeoDataFrames (translation, scale, rotation)
-    gdfs = transform_gdfs(gdfs, x, y, scale_x, scale_y, rotation, logging=logging)
-
-    # 6. Apply a postprocessing function to the GeoDataFrames, if provided
-    gdfs = postprocessing(gdfs)
-
-    # 7. Create background GeoDataFrame and get (x,y) bounds
-    background, xmin, ymin, xmax, ymax, dx, dy = create_background(
-        gdfs, style, logging=logging
-    )
-
-    # 8. Draw layers
-    draw_layers(layers, gdfs, style, fig, ax, vsk, mode, logging=logging)
-
-    # 9. Draw keypoints
-    keypoints = draw_keypoints(keypoints, gdfs, ax, logging=logging)
-
-    # 9. Draw background
-    draw_background(background, ax, style, mode, logging=logging)
-
-    # 10. Draw credit message
-    draw_credit(ax, background, credit, mode, multiplot, logging=logging)
-
-    # 11. Draw hillshade
-    draw_hillshade(
-        layers,
-        gdfs,
-        ax,
-        logging=logging,
-        **(layers["hillshade"] if "hillshade" in layers else {}),
-    )
-
-    # 12. Create Plot object
-    plot = Plot(gdfs, fig, ax, background, keypoints)
-
-    # 13. Save plot as image
-    if save_as is not None:
-        plt.savefig(save_as)
-
-    # 14. Show plot
-    if show:
-        if mode == "plotter":
-            vsk.display()
-        elif mode == "matplotlib":
-            plt.show()
-        else:
-            raise Exception(f"Unknown mode {mode}")
-    else:
-        plt.close()
-
-    return plot
-
-
-
- -
- -
- - -

- plot_gdf(layer, gdf, ax, mode='matplotlib', vsk=None, palette=None, width=None, union=False, dilate_points=None, dilate_lines=None, **kwargs) - -

- - -
- -

Plot a layer

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- layer - - str - -
-

layer name

-
-
- required -
- gdf - - GeoDataFrame - -
-

GeoDataFrame

-
-
- required -
- ax - - Axes - -
-

matplotlib axis object

-
-
- required -
- mode - - str - -
-

drawing mode. Options: 'matplotlib', 'vsketch'. Defaults to 'matplotlib'

-
-
- 'matplotlib' -
- vsk - - Optional[SketchClass] - -
-

Vsketch object. Mandatory if mode == 'plotter'

-
-
- None -
- palette - - Optional[List[str]] - -
-

Color palette. Defaults to None.

-
-
- None -
- width - - Optional[Union[dict, float]] - -
-

Street widths. Either a dictionary or a float. Defaults to None.

-
-
- None -
- union - - bool - -
-

Whether to join geometries. Defaults to False.

-
-
- False -
- dilate_points - - Optional[float] - -
-

Amount of dilation to be applied to point (1D) geometries. Defaults to None.

-
-
- None -
- dilate_lines - - Optional[float] - -
-

Amount of dilation to be applied to line (2D) geometries. Defaults to None.

-
-
- None -
- - -

Raises:

- - - - - - - - - - - - - -
TypeDescription
- Exception - -
-

description

-
-
- - -
- Source code in prettymaps/draw.py -
292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
def plot_gdf(
-    layer: str,
-    gdf: gp.GeoDataFrame,
-    ax: matplotlib.axes.Axes,
-    mode: str = "matplotlib",
-    # vsk: Optional[vsketch.SketchClass] = None,
-    vsk=None,
-    palette: Optional[List[str]] = None,
-    width: Optional[Union[dict, float]] = None,
-    union: bool = False,
-    dilate_points: Optional[float] = None,
-    dilate_lines: Optional[float] = None,
-    **kwargs,
-) -> None:
-    """
-    Plot a layer
-
-    Args:
-        layer (str): layer name
-        gdf (gp.GeoDataFrame): GeoDataFrame
-        ax (matplotlib.axes.Axes): matplotlib axis object
-        mode (str): drawing mode. Options: 'matplotlib', 'vsketch'. Defaults to 'matplotlib'
-        vsk (Optional[vsketch.SketchClass]): Vsketch object. Mandatory if mode == 'plotter'
-        palette (Optional[List[str]], optional): Color palette. Defaults to None.
-        width (Optional[Union[dict, float]], optional): Street widths. Either a dictionary or a float. Defaults to None.
-        union (bool, optional): Whether to join geometries. Defaults to False.
-        dilate_points (Optional[float], optional): Amount of dilation to be applied to point (1D) geometries. Defaults to None.
-        dilate_lines (Optional[float], optional): Amount of dilation to be applied to line (2D) geometries. Defaults to None.
-
-    Raises:
-        Exception: _description_
-    """
-
-    # Get hatch and hatch_c parameter
-    hatch_c = kwargs.pop("hatch_c") if "hatch_c" in kwargs else None
-
-    # Convert GDF to shapely geometries
-    geometries = gdf_to_shapely(
-        layer, gdf, width, point_size=dilate_points, line_width=dilate_lines
-    )
-
-    # Unite geometries
-    if union:
-        geometries = shapely.ops.unary_union(GeometryCollection([geometries]))
-
-    if (palette is None) and ("fc" in kwargs) and (type(kwargs["fc"]) != str):
-        palette = kwargs.pop("fc")
-
-    for shape in geometries.geoms if hasattr(geometries, "geoms") else [geometries]:
-        if mode == "matplotlib":
-            if type(shape) in [Polygon, MultiPolygon]:
-                # Plot main shape (without silhouette)
-                ax.add_patch(
-                    PolygonPatch(
-                        shape,
-                        lw=0,
-                        ec=(
-                            hatch_c
-                            if hatch_c
-                            else kwargs["ec"] if "ec" in kwargs else None
-                        ),
-                        fc=(
-                            kwargs["fc"]
-                            if "fc" in kwargs
-                            else np.random.choice(palette) if palette else None
-                        ),
-                        **{
-                            k: v
-                            for k, v in kwargs.items()
-                            if k not in ["lw", "ec", "fc"]
-                        },
-                    ),
-                )
-                # Plot just silhouette
-                ax.add_patch(
-                    PolygonPatch(
-                        shape,
-                        fill=False,
-                        **{
-                            k: v
-                            for k, v in kwargs.items()
-                            if k not in ["hatch", "fill"]
-                        },
-                    )
-                )
-            elif type(shape) == LineString:
-                ax.plot(
-                    *shape.xy,
-                    c=kwargs["ec"] if "ec" in kwargs else None,
-                    **{
-                        k: v
-                        for k, v in kwargs.items()
-                        if k in ["lw", "ls", "dashes", "zorder"]
-                    },
-                )
-            elif type(shape) == MultiLineString:
-                for c in shape.geoms:
-                    ax.plot(
-                        *c.xy,
-                        c=kwargs["ec"] if "ec" in kwargs else None,
-                        **{
-                            k: v
-                            for k, v in kwargs.items()
-                            if k in ["lw", "lt", "dashes", "zorder"]
-                        },
-                    )
-        elif mode == "plotter":
-            if ("draw" not in kwargs) or kwargs["draw"]:
-
-                # Set stroke
-                if "stroke" in kwargs:
-                    vsk.stroke(kwargs["stroke"])
-                else:
-                    vsk.stroke(1)
-
-                # Set pen width
-                if "penWidth" in kwargs:
-                    vsk.penWidth(kwargs["penWidth"])
-                else:
-                    vsk.penWidth(0.3)
-
-                if "fill" in kwargs:
-                    vsk.fill(kwargs["fill"])
-                else:
-                    vsk.noFill()
-
-                vsk.geometry(shape)
-        else:
-            raise Exception(f"Unknown mode {mode}")
-
-
-
- -
- -
- - -

- presets_directory() - -

- - -
- -

Returns the path to the 'presets' directory. -This function constructs the path to the 'presets' directory, which is -located in the same directory as the current script file. -Returns: - str: The full path to the 'presets' directory.

- - -
- Source code in prettymaps/draw.py -
698
-699
-700
-701
-702
-703
-704
-705
-706
-707
def presets_directory():
-    """
-    Returns the path to the 'presets' directory.
-    This function constructs the path to the 'presets' directory, which is
-    located in the same directory as the current script file.
-    Returns:
-        str: The full path to the 'presets' directory.
-    """
-
-    return os.path.join(pathlib.Path(__file__).resolve().parent, "presets")
-
-
-
- -
- -
- - -

- read_preset(name) - -

- - -
- -

Read a preset from the presets folder (prettymaps/presets/)

- - -

Parameters:

- - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- name - - str - -
-

Preset name

-
-
- required -
- - -

Returns:

- - - - - - - - - - - - - -
TypeDescription
- Dict[str, dict] - -
-

parameters dictionary

-
-
- - -
- Source code in prettymaps/draw.py -
748
-749
-750
-751
-752
-753
-754
-755
-756
-757
-758
-759
-760
-761
-762
def read_preset(name: str) -> Dict[str, dict]:
-    """
-    Read a preset from the presets folder (prettymaps/presets/)
-
-    Args:
-        name (str): Preset name
-
-    Returns:
-        (Dict[str,dict]): parameters dictionary
-    """
-    path = os.path.join(presets_directory(), f"{name}.json")
-    with open(path, "r") as f:
-        # Load params from JSON file
-        params = json.load(f)
-    return params
-
-
-
- -
- -
- - -

- transform_gdfs(gdfs, x=0, y=0, scale_x=1, scale_y=1, rotation=0, logging=False) - -

- - -
- -

Apply geometric transformations to dictionary of GeoDataFrames

- - -

Parameters:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescriptionDefault
- gdfs - - Dict[str, GeoDataFrame] - -
-

Dictionary of GeoDataFrames

-
-
- required -
- x - - float - -
-

x-axis translation. Defaults to 0.

-
-
- 0 -
- y - - float - -
-

y-axis translation. Defaults to 0.

-
-
- 0 -
- scale_x - - float - -
-

x-axis scale. Defaults to 1.

-
-
- 1 -
- scale_y - - float - -
-

y-axis scale. Defaults to 1.

-
-
- 1 -
- rotation - - float - -
-

rotation angle (in radians). Defaults to 0.

-
-
- 0 -
- - -

Returns:

- - - - - - - - - - - - - -
TypeDescription
- Dict[str, GeoDataFrame] - -
-

Dict[str, gp.GeoDataFrame]: dictionary of transformed GeoDataFrames

-
-
- - -
- Source code in prettymaps/draw.py -
647
-648
-649
-650
-651
-652
-653
-654
-655
-656
-657
-658
-659
-660
-661
-662
-663
-664
-665
-666
-667
-668
-669
-670
-671
-672
-673
-674
-675
-676
-677
-678
-679
-680
-681
-682
-683
-684
-685
-686
-687
-688
-689
-690
@log_execution_time
-def transform_gdfs(
-    gdfs: Dict[str, gp.GeoDataFrame],
-    x: float = 0,
-    y: float = 0,
-    scale_x: float = 1,
-    scale_y: float = 1,
-    rotation: float = 0,
-    logging=False,
-) -> Dict[str, gp.GeoDataFrame]:
-    """
-    Apply geometric transformations to dictionary of GeoDataFrames
-
-    Args:
-        gdfs (Dict[str, gp.GeoDataFrame]): Dictionary of GeoDataFrames
-        x (float, optional): x-axis translation. Defaults to 0.
-        y (float, optional): y-axis translation. Defaults to 0.
-        scale_x (float, optional): x-axis scale. Defaults to 1.
-        scale_y (float, optional): y-axis scale. Defaults to 1.
-        rotation (float, optional): rotation angle (in radians). Defaults to 0.
-
-    Returns:
-        Dict[str, gp.GeoDataFrame]: dictionary of transformed GeoDataFrames
-    """
-    # Project geometries
-    gdfs = {
-        name: ox.project_gdf(gdf) if len(gdf) > 0 else gdf for name, gdf in gdfs.items()
-    }
-    # Create geometry collection from gdfs' geometries
-    collection = GeometryCollection(
-        [GeometryCollection(list(gdf.geometry)) for gdf in gdfs.values()]
-    )
-    # Translation, scale & rotation
-    collection = shapely.affinity.translate(collection, x, y)
-    collection = shapely.affinity.scale(collection, scale_x, scale_y)
-    collection = shapely.affinity.rotate(collection, rotation)
-    # Update geometries
-    for i, layer in enumerate(gdfs):
-        gdfs[layer].geometry = list(collection.geoms[i].geoms)
-        # Reproject
-        if len(gdfs[layer]) > 0:
-            gdfs[layer] = ox.project_gdf(gdfs[layer], to_crs="EPSG:4326")
-
-    return gdfs
-
-
-
- -
- - - -
- -
- -

- - -
- - - -

- prettymaps.fetch - - -

- -
- -

Prettymaps - A minimal Python library to draw pretty maps from OpenStreetMap Data -Copyright (C) 2021 Marcelo Prates

-

This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published -by the Free Software Foundation, either version 3 of the License, or -(at your option) any later version.

-

This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details.

-

You should have received a copy of the GNU Affero General Public License -along with this program. If not, see https://www.gnu.org/licenses/.

- - - - - - - - - -
- - - - - - - - - -
- - -

- get_keypoints(perimeter, tags={'place': 'quarter', 'highway': True, 'building': True, 'landuse': True, 'natural': True, 'waterway': True, 'amenity': True, 'leisure': True, 'shop': True, 'public_transport': True, 'tourism': True, 'historic': True, 'barrier': True, 'power': True, 'railway': True, 'cycleway': True, 'footway': True, 'healthcare': True, 'office': True, 'craft': True, 'man_made': True, 'boundary': True}) - -

- - -
- -

Extract keypoints from a given perimeter based on specified tags.

-

Parameters: -perimeter (shapely.geometry.Polygon): The polygon representing the area of interest. -tags (dict, optional): A dictionary of tags to filter the keypoints. The keys are tag names and the values are booleans indicating whether to include the tag. Default includes a variety of common tags.

-

Returns: -geopandas.GeoDataFrame: A GeoDataFrame containing the keypoints that match the specified tags within the given perimeter.

- - -
- Source code in prettymaps/fetch.py -
 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
def get_keypoints(
-    perimeter,
-    tags={
-        "place": "quarter",
-        "highway": True,
-        "building": True,
-        "landuse": True,
-        "natural": True,
-        "waterway": True,
-        "amenity": True,
-        "leisure": True,
-        "shop": True,
-        "public_transport": True,
-        "tourism": True,
-        "historic": True,
-        "barrier": True,
-        "power": True,
-        "railway": True,
-        "cycleway": True,
-        "footway": True,
-        "healthcare": True,
-        "office": True,
-        "craft": True,
-        "man_made": True,
-        "boundary": True,
-    },
-):
-    """
-    Extract keypoints from a given perimeter based on specified tags.
-
-    Parameters:
-    perimeter (shapely.geometry.Polygon): The polygon representing the area of interest.
-    tags (dict, optional): A dictionary of tags to filter the keypoints. The keys are tag names and the values are booleans indicating whether to include the tag. Default includes a variety of common tags.
-
-    Returns:
-    geopandas.GeoDataFrame: A GeoDataFrame containing the keypoints that match the specified tags within the given perimeter.
-    """
-    keypoints_df = ox.features_from_polygon(perimeter, tags=tags)
-
-    return keypoints_df
-
-
-
- -
- -
- - -

- merge_tags(layers_dict) - -

- - -
- -

Merge tags from a dictionary of layers into a single dictionary.

-

Parameters: -layers_dict (dict): Dictionary of layers with their respective tags.

-

Returns: -dict: Merged dictionary of tags.

- - -
- Source code in prettymaps/fetch.py -
522
-523
-524
-525
-526
-527
-528
-529
-530
-531
-532
-533
-534
-535
-536
-537
-538
-539
-540
-541
-542
-543
-544
-545
-546
-547
-548
-549
-550
-551
-552
-553
-554
-555
-556
-557
-558
-559
-560
-561
-562
-563
-564
-565
-566
-567
-568
-569
def merge_tags(layers_dict: dict) -> dict:
-    """
-    Merge tags from a dictionary of layers into a single dictionary.
-
-    Parameters:
-    layers_dict (dict): Dictionary of layers with their respective tags.
-
-    Returns:
-    dict: Merged dictionary of tags.
-    """
-
-    layers_dict = deepcopy(layers_dict)
-    merged_tags = {}
-
-    def _merge(d: dict):
-        for key, value in d.items():
-            if isinstance(value, dict):
-                if "tags" in value:
-                    for tag_key, tag_value in value["tags"].items():
-                        if tag_key in merged_tags:
-                            if isinstance(merged_tags[tag_key], list):
-                                if isinstance(tag_value, list):
-                                    merged_tags[tag_key].extend(tag_value)
-                                else:
-                                    merged_tags[tag_key].append(tag_value)
-                            else:
-                                merged_tags[tag_key] = (
-                                    [merged_tags[tag_key], tag_value]
-                                    if not isinstance(tag_value, list)
-                                    else [merged_tags[tag_key]] + tag_value
-                                )
-                        else:
-                            merged_tags[tag_key] = (
-                                tag_value
-                                if isinstance(tag_value, list)
-                                else [tag_value]
-                            )
-                _merge(value)
-
-    _merge(layers_dict)
-
-    # Simplify lists with a single element
-    merged_tags = {
-        k: (v[0] if isinstance(v, list) and len(v) == 1 else v)
-        for k, v in merged_tags.items()
-    }
-
-    return merged_tags
-
-
-
- -
- -
- - -

- obtain_elevation(gdf) - -

- - -
- -

Download all SRTM elevation tiles for the given polygon in a GeoDataFrame.

-

Parameters: -gdf (GeoDataFrame): GeoDataFrame containing the polygon. -output_dir (str): Directory to save the downloaded tiles.

- - -
- Source code in prettymaps/fetch.py -
103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
def obtain_elevation(gdf):
-    """
-    Download all SRTM elevation tiles for the given polygon in a GeoDataFrame.
-
-    Parameters:
-    gdf (GeoDataFrame): GeoDataFrame containing the polygon.
-    output_dir (str): Directory to save the downloaded tiles.
-    """
-
-    # Ensure the GeoDataFrame has a single polygon
-    if len(gdf) != 1:
-        raise ValueError("GeoDataFrame must contain a single polygon")
-
-    with warnings.catch_warnings():
-        warnings.simplefilter("ignore")
-        subprocess.run(
-            ["eio", "clean"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
-        )
-
-    # Get the bounding box of the polygon
-    bounds = gdf.total_bounds
-    min_lon, min_lat, max_lon, max_lat = bounds
-
-    # Configure the bounding box for the elevation library
-
-    output_file = os.path.join(os.getcwd(), "elevation.tif")
-    elevation.clip(
-        bounds=(min_lon, min_lat, max_lon, max_lat),
-        output=output_file,
-        margin="10%",
-        cache_dir=".",
-    )
-
-    # subprocess.run(
-    #    [
-    #        "gdalwarp",
-    #        "-tr",
-    #        "30",
-    #        "30",
-    #        "-r",
-    #        "cubic",
-    #        "elevation.tif",
-    #        "resampled_elevation.tif",
-    #    ],
-    #    # stdout=subprocess.DEVNULL,
-    #    # stderr=subprocess.DEVNULL,
-    # )
-
-    raster = rxr.open_rasterio(output_file).squeeze()
-
-    raster = raster.rio.reproject(CRS.from_string(ox.project_gdf(gdf).crs.to_string()))
-
-    # convert to numpy array
-    elevation_data = raster.data
-
-    return elevation_data
-
-
-
- -
- -
- - -

- read_from_cache(perimeter, layer_kwargs, cache_dir='prettymaps_cache') - -

- - -
- -

Read a GeoDataFrame from the cache based on the perimeter and layer arguments.

-

Parameters: -perimeter (GeoDataFrame): The perimeter GeoDataFrame. -layer_kwargs (dict): Dictionary of layer arguments. -cache_dir (str): Directory to read the cached GeoDataFrame from.

-

Returns: -GeoDataFrame: The cached GeoDataFrame, or None if it does not exist.

- - -
- Source code in prettymaps/fetch.py -
348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
def read_from_cache(
-    perimeter: GeoDataFrame,
-    layer_kwargs: dict,
-    cache_dir: str = "prettymaps_cache",
-) -> GeoDataFrame:
-    """
-    Read a GeoDataFrame from the cache based on the perimeter and layer arguments.
-
-    Parameters:
-    perimeter (GeoDataFrame): The perimeter GeoDataFrame.
-    layer_kwargs (dict): Dictionary of layer arguments.
-    cache_dir (str): Directory to read the cached GeoDataFrame from.
-
-    Returns:
-    GeoDataFrame: The cached GeoDataFrame, or None if it does not exist.
-    """
-    np.random.seed(0)
-    # Create hash from perimeter
-    perimeter_hash = hash(perimeter["geometry"].to_json())
-    # Create hash from kwargs
-    kwargs_hash = hash(str(layer_kwargs))
-    # Join hashes
-    hash_str = f"{perimeter_hash}_{kwargs_hash}"
-
-    cache_path = os.path.join(cache_dir, f"{hash_str}.geojson")
-
-    # Check if the gdf is cached
-    if os.path.exists(cache_path):
-        # Read cached gdf
-        return gp.read_file(cache_path)
-    else:
-        return None
-
-
-
- -
- -
- - -

- unified_osm_request(perimeter, layers_dict, logging=False) - -

- - -
- -

Unify all OSM requests into one to improve efficiency.

-

Parameters: -perimeter (GeoDataFrame): The perimeter GeoDataFrame. -layers_dict (dict): Dictionary of layers to fetch. -logging (bool): Enable or disable logging.

-

Returns: -dict: Dictionary of GeoDataFrames for each layer.

- - -
- Source code in prettymaps/fetch.py -
572
-573
-574
-575
-576
-577
-578
-579
-580
-581
-582
-583
-584
-585
-586
-587
-588
-589
-590
-591
-592
-593
-594
-595
-596
-597
-598
-599
-600
-601
-602
-603
-604
-605
-606
-607
-608
-609
-610
-611
-612
-613
-614
-615
-616
-617
-618
-619
-620
-621
-622
-623
-624
-625
-626
-627
-628
-629
-630
-631
-632
-633
-634
-635
-636
-637
-638
-639
-640
-641
-642
-643
-644
-645
-646
-647
-648
-649
-650
-651
-652
-653
-654
-655
-656
-657
-658
-659
-660
-661
-662
-663
-664
-665
-666
-667
-668
-669
-670
-671
-672
-673
-674
-675
-676
-677
-678
-679
-680
-681
-682
-683
-684
-685
-686
-687
-688
-689
-690
-691
-692
-693
-694
-695
-696
def unified_osm_request(
-    perimeter: GeoDataFrame, layers_dict: dict, logging: bool = False
-) -> dict:
-    """
-    Unify all OSM requests into one to improve efficiency.
-
-    Parameters:
-    perimeter (GeoDataFrame): The perimeter GeoDataFrame.
-    layers_dict (dict): Dictionary of layers to fetch.
-    logging (bool): Enable or disable logging.
-
-    Returns:
-    dict: Dictionary of GeoDataFrames for each layer.
-    """
-    # Apply tolerance to the perimeter
-    perimeter_with_tolerance = ox.project_gdf(perimeter).buffer(0).to_crs(4326)
-    perimeter_with_tolerance = unary_union(perimeter_with_tolerance.geometry).buffer(0)
-
-    # Fetch from perimeter's bounding box, to avoid missing some geometries
-    bbox = box(*perimeter_with_tolerance.bounds)
-
-    # Initialize the result dictionary
-    gdfs = {}
-    ## Read layers from cache
-    # for layer, kwargs in layers_dict.items():
-    #    gdf = read_from_cache(perimeter, layers_dict[layer])
-    #    if gdf is not None:
-    #        gdfs[layer] = gdf
-
-    # Combine all tags into a single dictionary for a unified request
-    combined_tags = merge_tags(
-        {layer: kwargs for layer, kwargs in layers_dict.items() if layer not in gdfs}
-    )
-
-    # Fetch all features in one request
-    try:
-        all_features = ox.features_from_polygon(bbox, tags=combined_tags)
-    except Exception as e:
-        all_features = GeoDataFrame(geometry=[])
-
-    # Split the features into separate GeoDataFrames based on the layers_dict
-    for layer, kwargs in layers_dict.items():
-        if layer in gdfs:
-            continue
-        try:
-            if layer in ["streets", "railway", "waterway"]:
-                graph = ox.graph_from_polygon(
-                    bbox,
-                    custom_filter=kwargs.get("custom_filter"),
-                    truncate_by_edge=True,
-                )
-                gdf = ox.graph_to_gdfs(graph, nodes=False)
-            elif layer == "sea":
-                try:
-                    coastline = unary_union(
-                        ox.features_from_polygon(
-                            bbox, tags={"natural": "coastline"}
-                        ).geometry.tolist()
-                    )
-                    sea_candidates = bbox.difference(coastline.buffer(1e-9)).geoms
-                    drive = ox.graph_from_polygon(bbox, network_type="drive")
-                    drive = ox.graph_to_gdfs(drive, nodes=False)
-
-                    def filter_candidate(sea_candidate):
-                        intersections = drive.geometry.intersects(sea_candidate)
-                        if "bridge" in drive.columns:
-                            return not any(
-                                intersections
-                                & (
-                                    drive.loc[
-                                        drive.geometry.intersects(sea_candidate),
-                                        "bridge",
-                                    ]
-                                    != "yes"
-                                )
-                            )
-                        else:
-                            return not any(intersections)
-
-                    sea = unary_union(
-                        MultiPolygon(
-                            [
-                                candidate
-                                for candidate in sea_candidates
-                                if filter_candidate(candidate)
-                            ]
-                        ).geoms
-                    ).buffer(1e-8)
-                    gdf = GeoDataFrame(geometry=[sea], crs=perimeter.crs)
-                except:
-                    gdf = GeoDataFrame(geometry=[], crs=perimeter.crs)
-            else:
-                if kwargs.get("osmid") is None:
-                    if layer == "perimeter":
-                        gdf = perimeter
-                    else:
-                        layer_tags = kwargs.get("tags")
-                        gdf = gp.GeoDataFrame(geometry=[], crs=perimeter.crs)
-                        for key, value in layer_tags.items():
-                            if isinstance(value, bool) and value:
-                                filtered_features = all_features[
-                                    ~pd.isna(all_features[key])
-                                ]
-                            elif isinstance(value, list):
-                                filtered_features = all_features[
-                                    all_features[key].isin(value)
-                                ]
-                            else:
-                                filtered_features = all_features[
-                                    all_features[key] == value
-                                ]
-                            gdf = pd.concat([gdf, filtered_features], axis=0)
-                else:
-                    gdf = ox.geocode_to_gdf(kwargs.get("osmid"), by_osmid=True)
-
-            gdf = gdf.copy()
-            gdf.geometry = gdf.geometry.intersection(perimeter_with_tolerance)
-            gdf.drop(gdf[gdf.geometry.is_empty].index, inplace=True)
-            gdfs[layer] = gdf
-            # write_to_cache(perimeter, gdf, layers_dict[layer])
-        except Exception as e:
-            # print(f"Error fetching {layer}: {e}")
-            gdfs[layer] = GeoDataFrame(geometry=[])
-
-    return gdfs
-
-
-
- -
- -
- - -

- write_to_cache(perimeter, gdf, layer_kwargs, cache_dir='prettymaps_cache') - -

- - -
- -

Write a GeoDataFrame to the cache based on the perimeter and layer arguments.

-

Parameters: -perimeter (GeoDataFrame): The perimeter GeoDataFrame. -gdf (GeoDataFrame): The GeoDataFrame to cache. -layer_kwargs (dict): Dictionary of layer arguments. -cache_dir (str): Directory to save the cached GeoDataFrame.

- - -
- Source code in prettymaps/fetch.py -
314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
def write_to_cache(
-    perimeter: GeoDataFrame,
-    gdf: GeoDataFrame,
-    layer_kwargs: dict,
-    cache_dir: str = "prettymaps_cache",
-):
-    """
-    Write a GeoDataFrame to the cache based on the perimeter and layer arguments.
-
-    Parameters:
-    perimeter (GeoDataFrame): The perimeter GeoDataFrame.
-    gdf (GeoDataFrame): The GeoDataFrame to cache.
-    layer_kwargs (dict): Dictionary of layer arguments.
-    cache_dir (str): Directory to save the cached GeoDataFrame.
-    """
-    np.random.seed(0)
-    os.makedirs(cache_dir, exist_ok=True)
-
-    # Create hash from perimeter
-    perimeter_hash = hash(perimeter["geometry"].to_json())
-    # Create hash from kwargs
-    kwargs_hash = hash(str(layer_kwargs))
-    # Join hashes
-    hash_str = f"{perimeter_hash}_{kwargs_hash}"
-
-    cache_path = os.path.join(cache_dir, f"{hash_str}.geojson")
-
-    # Write gdf to cache
-    logging.getLogger().setLevel(logging.CRITICAL)
-    if not gdf.empty:
-        gdf.to_file(cache_path, driver="GeoJSON")
-    logging.getLogger().setLevel(logging.INFO)
-
-
-
- -
- - - -
- -
- -

- - -
- - - -

- prettymaps.utils - - -

- -
- - - - - - - - - -
- - - - - - - - - - - -
- -
- -
+

This page will contain the API reference for Prettymaps.

+

More details coming soon!

diff --git a/index.html b/index.html index 1608976..2dd750e 100644 --- a/index.html +++ b/index.html @@ -72,7 +72,7 @@
- + Skip to content @@ -213,19 +213,6 @@ - - @@ -238,52 +225,6 @@ - - - - @@ -352,41 +293,6 @@ - - -
@@ -401,28 +307,8 @@ -

prettymaps

-

A minimal Python library to draw pretty maps from OpenStreetMap data.

- -

Features

- -

Installation

-
pip install prettymaps
-
-

Quick Example

-
import prettymaps
-prettymaps.plot("Porto Alegre")
-
-
-

Data © OpenStreetMap contributors

+

Prettymaps Documentation

+

Welcome to the Prettymaps documentation site.

diff --git a/objects.inv b/objects.inv index 9bdfad5614f4eab5b0651c4536bff3a87bde14a6..e2c9fb411211f4ba24e6f0f26ccfffd120bba4e0 100644 GIT binary patch delta 14 VcmX@X+`>4ami;jk0|Pe$Hvl3E17H9E delta 340 zcmV-a0jvIm0muW8eSe*l-A=6CMK%l z?j~2~bB^tkWG0azU@jZWcx>|U9+It|n%4%idwG0no*(k9XtVW6CZ+LM%Azp&p-XX# zV*1s<2Eaup02A5PXvC$s2s0JZ8T+WatZl+Dp%CoQ>^n|1T7RvdA245SX`tzVk+g0d zBJ`yOI@^LIC_QHKgPNigNZ3)i3l`YZkdup2ZlJd_^b2Td+WsvuQ;{+EcQ^?cvAb-g zsHy73T_U3a(oWDtAWsK8X*E6nfoAF+h}l^J&QYX0hm536;ZQCcH@sZK5FfiRh%#LBmV|#xpJ`GDx@v| diff --git a/search/search_index.json b/search/search_index.json index 7f54754..12441bd 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"prettymaps","text":"

A minimal Python library to draw pretty maps from OpenStreetMap data.

  • Usage
  • API Reference
"},{"location":"#features","title":"Features","text":"
  • Draw beautiful maps from OSM data
  • Highly customizable layers and styles
  • Preset management
  • Keypoint highlighting
"},{"location":"#installation","title":"Installation","text":"
pip install prettymaps\n
"},{"location":"#quick-example","title":"Quick Example","text":"
import prettymaps\nprettymaps.plot(\"Porto Alegre\")\n

Data \u00a9 OpenStreetMap contributors

"},{"location":"api/","title":"API Reference","text":"

This page documents the main modules and functions of the prettymaps library. The API documentation is auto-generated from the code and includes all public classes and functions.

"},{"location":"api/#modules","title":"Modules","text":"
  • draw: Core drawing and plotting functions, including map rendering, layer management, and style handling.
  • fetch: Functions for fetching and processing OpenStreetMap data and elevation.
  • utils: Utility functions for logging, timing, and other helpers.
"},{"location":"api/#prettymaps.draw","title":"prettymaps.draw","text":"

Prettymaps - A minimal Python library to draw pretty maps from OpenStreetMap Data Copyright (C) 2021 Marcelo Prates

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.

"},{"location":"api/#prettymaps.draw.Plot","title":"Plot dataclass","text":"

Dataclass implementing a prettymaps Plot object.

Attributes:

Name Type Description geodataframes Dict[str, GeoDataFrame]

A dictionary of GeoDataFrames (one for each plot layer).

fig Figure

A matplotlib figure.

ax Axes

A matplotlib axis object.

background BaseGeometry

Background layer (shapely object).

keypoints GeoDataFrame

Keypoints GeoDataFrame.

Source code in prettymaps/draw.py
@dataclass\nclass Plot:\n    \"\"\"\n    Dataclass implementing a prettymaps Plot object.\n\n    Attributes:\n        geodataframes (Dict[str, gp.GeoDataFrame]): A dictionary of GeoDataFrames (one for each plot layer).\n        fig (matplotlib.figure.Figure): A matplotlib figure.\n        ax (matplotlib.axes.Axes): A matplotlib axis object.\n        background (BaseGeometry): Background layer (shapely object).\n        keypoints (gp.GeoDataFrame): Keypoints GeoDataFrame.\n    \"\"\"\n\n    geodataframes: Dict[str, gp.GeoDataFrame]\n    fig: matplotlib.figure.Figure\n    ax: matplotlib.axes.Axes\n    background: BaseGeometry\n    keypoints: gp.GeoDataFrame\n
"},{"location":"api/#prettymaps.draw.PolygonPatch","title":"PolygonPatch","text":"

Bases: PathPatch

A class to create a matplotlib PathPatch from a shapely geometry.

Attributes:

Name Type Description shape BaseGeometry

Shapely geometry.

kwargs BaseGeometry

Parameters for matplotlib's PathPatch constructor.

Methods:

Name Description __init__

BaseGeometry, **kwargs): Initialize the PolygonPatch with the given shapely geometry and additional parameters.

shape (BaseGeometry): Shapely geometry. kwargs: Parameters for matplotlib's PathPatch constructor.

Source code in prettymaps/draw.py
class PolygonPatch(PathPatch):\n    \"\"\"\n    A class to create a matplotlib PathPatch from a shapely geometry.\n\n    Attributes:\n        shape (BaseGeometry): Shapely geometry.\n        kwargs: Parameters for matplotlib's PathPatch constructor.\n\n    Methods:\n        __init__(shape: BaseGeometry, **kwargs):\n            Initialize the PolygonPatch with the given shapely geometry and additional parameters.\n\n\n            shape (BaseGeometry): Shapely geometry.\n            kwargs: Parameters for matplotlib's PathPatch constructor.\n    \"\"\"\n\n    def __init__(self, shape: BaseGeometry, **kwargs):\n        \"\"\"\n        Initialize the PolygonPatch.\n\n        Args:\n            shape (BaseGeometry): Shapely geometry\n            kwargs: parameters for matplotlib's PathPatch constructor\n        \"\"\"\n        # Init vertices and codes lists\n        vertices, codes = [], []\n        for geom in shape.geoms if hasattr(shape, \"geoms\") else [shape]:\n            for poly in geom.geoms if hasattr(geom, \"geoms\") else [geom]:\n                if type(poly) != Polygon:\n                    continue\n                # Get polygon's exterior and interiors\n                exterior = np.array(poly.exterior.xy)\n                interiors = [np.array(interior.xy) for interior in poly.interiors]\n                # Append to vertices and codes lists\n                vertices += [exterior] + interiors\n                codes += list(\n                    map(\n                        # Ring coding\n                        lambda p: [Path.MOVETO]\n                        + [Path.LINETO] * (p.shape[1] - 2)\n                        + [Path.CLOSEPOLY],\n                        [exterior] + interiors,\n                    )\n                )\n        # Initialize PathPatch with the generated Path\n        super().__init__(\n            Path(np.concatenate(vertices, 1).T, np.concatenate(codes)), **kwargs\n        )\n
"},{"location":"api/#prettymaps.draw.PolygonPatch.__init__","title":"__init__(shape, **kwargs)","text":"

Initialize the PolygonPatch.

Parameters:

Name Type Description Default shape BaseGeometry

Shapely geometry

required kwargs

parameters for matplotlib's PathPatch constructor

{} Source code in prettymaps/draw.py
def __init__(self, shape: BaseGeometry, **kwargs):\n    \"\"\"\n    Initialize the PolygonPatch.\n\n    Args:\n        shape (BaseGeometry): Shapely geometry\n        kwargs: parameters for matplotlib's PathPatch constructor\n    \"\"\"\n    # Init vertices and codes lists\n    vertices, codes = [], []\n    for geom in shape.geoms if hasattr(shape, \"geoms\") else [shape]:\n        for poly in geom.geoms if hasattr(geom, \"geoms\") else [geom]:\n            if type(poly) != Polygon:\n                continue\n            # Get polygon's exterior and interiors\n            exterior = np.array(poly.exterior.xy)\n            interiors = [np.array(interior.xy) for interior in poly.interiors]\n            # Append to vertices and codes lists\n            vertices += [exterior] + interiors\n            codes += list(\n                map(\n                    # Ring coding\n                    lambda p: [Path.MOVETO]\n                    + [Path.LINETO] * (p.shape[1] - 2)\n                    + [Path.CLOSEPOLY],\n                    [exterior] + interiors,\n                )\n            )\n    # Initialize PathPatch with the generated Path\n    super().__init__(\n        Path(np.concatenate(vertices, 1).T, np.concatenate(codes)), **kwargs\n    )\n
"},{"location":"api/#prettymaps.draw.Preset","title":"Preset dataclass","text":"

Dataclass implementing a prettymaps Preset object.

Attributes:

Name Type Description params dict

Dictionary of prettymaps.plot() parameters.

Source code in prettymaps/draw.py
@dataclass\nclass Preset:\n    \"\"\"\n    Dataclass implementing a prettymaps Preset object.\n\n    Attributes:\n        params (dict): Dictionary of prettymaps.plot() parameters.\n    \"\"\"\n\n    params: dict\n
"},{"location":"api/#prettymaps.draw.Subplot","title":"Subplot","text":"

Class implementing a prettymaps Subplot. Attributes: - query: prettymaps.plot() query - kwargs: dictionary of prettymaps.plot() parameters

Source code in prettymaps/draw.py
class Subplot:\n    \"\"\"\n    Class implementing a prettymaps Subplot. Attributes:\n    - query: prettymaps.plot() query\n    - kwargs: dictionary of prettymaps.plot() parameters\n    \"\"\"\n\n    def __init__(self, query, **kwargs):\n        self.query = query\n        self.kwargs = kwargs\n
"},{"location":"api/#prettymaps.draw.create_background","title":"create_background(gdfs, style, logging=False)","text":"

Create a background layer given a collection of GeoDataFrames

Parameters:

Name Type Description Default gdfs Dict[str, GeoDataFrame]

Dictionary of GeoDataFrames

required style Dict[str, dict]

Dictionary of matplotlib style parameters

required

Returns:

Type Description Tuple[BaseGeometry, float, float, float, float, float, float]

Tuple[BaseGeometry, float, float, float, float, float, float]: background geometry, bounds, width and height

Source code in prettymaps/draw.py
@log_execution_time\ndef create_background(\n    gdfs: Dict[str, gp.GeoDataFrame],\n    style: Dict[str, dict],\n    logging=False,\n) -> Tuple[BaseGeometry, float, float, float, float, float, float]:\n    \"\"\"\n    Create a background layer given a collection of GeoDataFrames\n\n    Args:\n        gdfs (Dict[str, gp.GeoDataFrame]): Dictionary of GeoDataFrames\n        style (Dict[str, dict]): Dictionary of matplotlib style parameters\n\n    Returns:\n        Tuple[BaseGeometry, float, float, float, float, float, float]: background geometry, bounds, width and height\n    \"\"\"\n\n    # Create background\n    background_pad = 1.1\n    if \"background\" in style and \"pad\" in style[\"background\"]:\n        background_pad = style[\"background\"].pop(\"pad\")\n\n    background = shapely.affinity.scale(\n        box(\n            *shapely.ops.unary_union(ox.project_gdf(gdfs[\"perimeter\"]).geometry).bounds\n        ),\n        background_pad,\n        background_pad,\n    )\n\n    if \"background\" in style and \"dilate\" in style[\"background\"]:\n        background = background.buffer(style[\"background\"].pop(\"dilate\"))\n\n    # Get bounds\n    xmin, ymin, xmax, ymax = background.bounds\n    dx, dy = xmax - xmin, ymax - ymin\n\n    return background, xmin, ymin, xmax, ymax, dx, dy\n
"},{"location":"api/#prettymaps.draw.create_preset","title":"create_preset(name, layers=None, style=None, circle=None, radius=None, dilate=None)","text":"

Create a preset file and save it on the presets folder (prettymaps/presets/) under name 'name.json'

Parameters:

Name Type Description Default name str

Preset name

required layers Dict[str, dict]

prettymaps.plot() 'layers' parameter dict. Defaults to None.

None style Dict[str, dict]

prettymaps.plot() 'style' parameter dict. Defaults to None.

None circle Optional[bool]

prettymaps.plot() 'circle' parameter. Defaults to None.

None radius Optional[Union[float, bool]]

prettymaps.plot() 'radius' parameter. Defaults to None.

None dilate Optional[Union[float, bool]]

prettymaps.plot() 'dilate' parameter. Defaults to None.

None Source code in prettymaps/draw.py
def create_preset(\n    name: str,\n    layers: Optional[Dict[str, dict]] = None,\n    style: Optional[Dict[str, dict]] = None,\n    circle: Optional[bool] = None,\n    radius: Optional[Union[float, bool]] = None,\n    dilate: Optional[Union[float, bool]] = None,\n) -> None:\n    \"\"\"\n    Create a preset file and save it on the presets folder (prettymaps/presets/) under name 'name.json'\n\n    Args:\n        name (str): Preset name\n        layers (Dict[str, dict], optional): prettymaps.plot() 'layers' parameter dict. Defaults to None.\n        style (Dict[str, dict], optional): prettymaps.plot() 'style' parameter dict. Defaults to None.\n        circle (Optional[bool], optional): prettymaps.plot() 'circle' parameter. Defaults to None.\n        radius (Optional[Union[float, bool]], optional): prettymaps.plot() 'radius' parameter. Defaults to None.\n        dilate (Optional[Union[float, bool]], optional): prettymaps.plot() 'dilate' parameter. Defaults to None.\n    \"\"\"\n\n    # if not os.path.isdir('presets'):\n    #    os.makedirs('presets')\n\n    path = os.path.join(presets_directory(), f\"{name}.json\")\n    with open(path, \"w\") as f:\n        json.dump(\n            {\n                \"layers\": layers,\n                \"style\": style,\n                \"circle\": circle,\n                \"radius\": radius,\n                \"dilate\": dilate,\n            },\n            f,\n            ensure_ascii=False,\n        )\n
"},{"location":"api/#prettymaps.draw.draw_credit","title":"draw_credit(ax, background, credit, mode, multiplot, logging=False)","text":"

Draws credit text on the plot.

Parameters:

Name Type Description Default ax Axes

Matplotlib axis object.

required background BaseGeometry

Background layer.

required credit Dict[str, Any]

Dictionary containing credit text and style parameters.

required mode str

Drawing mode. Options: 'matplotlib', 'plotter'.

required multiplot bool

Whether the plot is part of a multiplot.

required logging bool

Whether to enable logging. Defaults to False.

False Source code in prettymaps/draw.py
@log_execution_time\ndef draw_credit(\n    ax: matplotlib.axes.Axes,\n    background: BaseGeometry,\n    credit: Dict[str, Any],\n    mode: str,\n    multiplot: bool,\n    logging: bool = False,\n) -> None:\n    \"\"\"\n    Draws credit text on the plot.\n\n    Args:\n        ax (matplotlib.axes.Axes): Matplotlib axis object.\n        background (BaseGeometry): Background layer.\n        credit (Dict[str, Any]): Dictionary containing credit text and style parameters.\n        mode (str): Drawing mode. Options: 'matplotlib', 'plotter'.\n        multiplot (bool): Whether the plot is part of a multiplot.\n        logging (bool, optional): Whether to enable logging. Defaults to False.\n    \"\"\"\n    if (mode == \"matplotlib\") and (credit != False) and (not multiplot):\n        draw_text(ax, credit, background)\n
"},{"location":"api/#prettymaps.draw.draw_text","title":"draw_text(ax, params, background)","text":"

Draw text with content and matplotlib style parameters specified by 'params' dictionary. params['text'] should contain the message to be drawn.

Parameters:

Name Type Description Default ax Axes

Matplotlib axis object.

required params Dict[str, Any]

Matplotlib style parameters for drawing text. params['text'] should contain the message to be drawn.

required background BaseGeometry

Background layer.

required Source code in prettymaps/draw.py
def draw_text(\n    ax: matplotlib.axes.Axes, params: Dict[str, Any], background: BaseGeometry\n) -> None:\n    \"\"\"\n    Draw text with content and matplotlib style parameters specified by 'params' dictionary.\n    params['text'] should contain the message to be drawn.\n\n    Args:\n        ax (matplotlib.axes.Axes): Matplotlib axis object.\n        params (Dict[str, Any]): Matplotlib style parameters for drawing text. params['text'] should contain the message to be drawn.\n        background (BaseGeometry): Background layer.\n    \"\"\"\n    # Override default osm_credit dict with provided parameters\n    params = override_params(\n        dict(\n            text=\"\\n\".join(\n                [\n                    \"data \u00a9 OpenStreetMap contributors\",\n                    \"github.com/marceloprates/prettymaps\",\n                ]\n            ),\n            x=0,\n            y=1,\n            horizontalalignment=\"left\",\n            verticalalignment=\"top\",\n            bbox=dict(boxstyle=\"square\", fc=\"#fff\", ec=\"#000\"),\n            # fontfamily=\"Ubuntu Mono\",\n        ),\n        params,\n    )\n    x, y, text = [params.pop(k) for k in [\"x\", \"y\", \"text\"]]\n\n    # Get background bounds\n    xmin, ymin, xmax, ymax = background.bounds\n\n    x = np.interp([x], [0, 1], [xmin, xmax])[0]\n    y = np.interp([y], [0, 1], [ymin, ymax])[0]\n\n    ax.text(x, y, text, zorder=1000, **params)\n
"},{"location":"api/#prettymaps.draw.gdf_to_shapely","title":"gdf_to_shapely(layer, gdf, width=None, point_size=None, line_width=None, **kwargs)","text":"

Convert a dict of GeoDataFrames to a dict of shapely geometries

Parameters:

Name Type Description Default layer str

Layer name

required gdf GeoDataFrame

Input GeoDataFrame

required width Optional[Union[dict, float]]

Street network width. Can be either a dictionary or a float. Defaults to None.

None point_size Optional[float]

Point geometries (1D) will be dilated by this amount. Defaults to None.

None line_width Optional[float]

Line geometries (2D) will be dilated by this amount. Defaults to None.

None

Returns:

Name Type Description GeometryCollection GeometryCollection

Output GeoDataFrame

Source code in prettymaps/draw.py
def gdf_to_shapely(\n    layer: str,\n    gdf: gp.GeoDataFrame,\n    width: Optional[Union[dict, float]] = None,\n    point_size: Optional[float] = None,\n    line_width: Optional[float] = None,\n    **kwargs,\n) -> GeometryCollection:\n    \"\"\"\n    Convert a dict of GeoDataFrames to a dict of shapely geometries\n\n    Args:\n        layer (str): Layer name\n        gdf (gp.GeoDataFrame): Input GeoDataFrame\n        width (Optional[Union[dict, float]], optional): Street network width. Can be either a dictionary or a float. Defaults to None.\n        point_size (Optional[float], optional): Point geometries (1D) will be dilated by this amount. Defaults to None.\n        line_width (Optional[float], optional): Line geometries (2D) will be dilated by this amount. Defaults to None.\n\n    Returns:\n        GeometryCollection: Output GeoDataFrame\n    \"\"\"\n\n    # Project gdf if applicable\n    if not gdf.empty and gdf.crs is not None:\n        gdf = ox.project_gdf(gdf)\n\n    if layer in [\"streets\", \"railway\", \"waterway\"]:\n        geometries = graph_to_shapely(gdf, width)\n    else:\n        geometries = geometries_to_shapely(\n            gdf, point_size=point_size, line_width=line_width\n        )\n\n    return geometries\n
"},{"location":"api/#prettymaps.draw.geometries_to_shapely","title":"geometries_to_shapely(gdf, point_size=None, line_width=None)","text":"

Convert geometries in GeoDataFrame to shapely format

Parameters:

Name Type Description Default gdf GeoDataFrame

Input GeoDataFrame

required point_size Optional[float]

Point geometries (1D) will be dilated by this amount. Defaults to None.

None line_width Optional[float]

Line geometries (2D) will be dilated by this amount. Defaults to None.

None

Returns:

Name Type Description GeometryCollection GeometryCollection

Shapely geometries computed from GeoDataFrame geometries

Source code in prettymaps/draw.py
def geometries_to_shapely(\n    gdf: gp.GeoDataFrame,\n    point_size: Optional[float] = None,\n    line_width: Optional[float] = None,\n) -> GeometryCollection:\n    \"\"\"\n    Convert geometries in GeoDataFrame to shapely format\n\n    Args:\n        gdf (gp.GeoDataFrame): Input GeoDataFrame\n        point_size (Optional[float], optional): Point geometries (1D) will be dilated by this amount. Defaults to None.\n        line_width (Optional[float], optional): Line geometries (2D) will be dilated by this amount. Defaults to None.\n\n    Returns:\n        GeometryCollection: Shapely geometries computed from GeoDataFrame geometries\n    \"\"\"\n\n    geoms = gdf.geometry.tolist()\n    collections = [x for x in geoms if type(x) == GeometryCollection]\n    points = [x for x in geoms if type(x) == Point] + [\n        y for x in collections for y in x.geoms if type(y) == Point\n    ]\n    lines = [x for x in geoms if type(x) in [LineString, MultiLineString]] + [\n        y\n        for x in collections\n        for y in x.geoms\n        if type(y) in [LineString, MultiLineString]\n    ]\n    polys = [x for x in geoms if type(x) in [Polygon, MultiPolygon]] + [\n        y for x in collections for y in x.geoms if type(y) in [Polygon, MultiPolygon]\n    ]\n\n    # Convert points into circles with radius \"point_size\"\n    if point_size:\n        points = [x.buffer(point_size) for x in points] if point_size > 0 else []\n    if line_width:\n        lines = [x.buffer(line_width) for x in lines] if line_width > 0 else []\n\n    return GeometryCollection(list(points) + list(lines) + list(polys))\n
"},{"location":"api/#prettymaps.draw.graph_to_shapely","title":"graph_to_shapely(gdf, width=1.0)","text":"

Given a GeoDataFrame containing a graph (street newtork), convert them to shapely geometries by applying dilation given by 'width'

Parameters:

Name Type Description Default gdf GeoDataFrame

input GeoDataFrame containing graph (street network) geometries

required width float

Line geometries will be dilated by this amount. Defaults to 1..

1.0

Returns:

Name Type Description BaseGeometry BaseGeometry

Shapely

Source code in prettymaps/draw.py
def graph_to_shapely(gdf: gp.GeoDataFrame, width: float = 1.0) -> BaseGeometry:\n    \"\"\"\n    Given a GeoDataFrame containing a graph (street newtork),\n    convert them to shapely geometries by applying dilation given by 'width'\n\n    Args:\n        gdf (gp.GeoDataFrame): input GeoDataFrame containing graph (street network) geometries\n        width (float, optional): Line geometries will be dilated by this amount. Defaults to 1..\n\n    Returns:\n        BaseGeometry: Shapely\n    \"\"\"\n\n    def highway_to_width(highway):\n        if (type(highway) == str) and (highway in width):\n            return width[highway]\n        elif isinstance(highway, Iterable):\n            for h in highway:\n                if h in width:\n                    return width[h]\n            return np.nan\n        else:\n            return np.nan\n\n    # Annotate GeoDataFrame with the width for each highway type\n    gdf[\"width\"] = (\n        gdf[\"highway\"].map(highway_to_width) if type(width) == dict else width\n    )\n\n    # Remove rows with inexistent width\n    gdf.drop(gdf[gdf.width.isna()].index, inplace=True)\n\n    with warnings.catch_warnings():\n        # Supress shapely.errors.ShapelyDeprecationWarning\n        warnings.simplefilter(\"ignore\", shapely.errors.ShapelyDeprecationWarning)\n        if not all(gdf.width.isna()):\n            # Dilate geometries based on their width\n            gdf.geometry = gdf.apply(\n                lambda row: row[\"geometry\"].buffer(row.width), axis=1\n            )\n\n    return shapely.ops.unary_union(gdf.geometry)\n
"},{"location":"api/#prettymaps.draw.manage_presets","title":"manage_presets(load_preset, save_preset, update_preset, layers, style, circle, radius, dilate, logging=False)","text":"

summary

Parameters:

Name Type Description Default load_preset Optional[str]

Load preset named 'load_preset', if provided

required save_preset Optional[str]

Save preset to file named 'save_preset', if provided

required update_preset Optional[str]

Load, update and save preset named 'update_preset', if provided

required layers Dict[str, dict]

prettymaps.plot() 'layers' parameter dict

required style Dict[str, dict]

prettymaps.plot() 'style' parameter dict

required circle Optional[bool]

prettymaps.plot() 'circle' parameter

required radius Optional[Union[float, bool]]

prettymaps.plot() 'radius' parameter

required dilate Optional[Union[float, bool]]

prettymaps.plot() 'dilate' parameter

required

Returns:

Type Description Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]]

Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]]: Updated layers, style, circle, radius, dilate parameters

Source code in prettymaps/draw.py
@log_execution_time\ndef manage_presets(\n    load_preset: Optional[str],\n    save_preset: bool,\n    update_preset: Optional[str],\n    layers: Dict[str, dict],\n    style: Dict[str, dict],\n    circle: Optional[bool],\n    radius: Optional[Union[float, bool]],\n    dilate: Optional[Union[float, bool]],\n    logging=False,\n) -> Tuple[\n    dict,\n    dict,\n    Optional[float],\n    Optional[Union[float, bool]],\n    Optional[Union[float, bool]],\n]:\n    \"\"\"_summary_\n\n    Args:\n        load_preset (Optional[str]): Load preset named 'load_preset', if provided\n        save_preset (Optional[str]): Save preset to file named 'save_preset', if provided\n        update_preset (Optional[str]): Load, update and save preset named 'update_preset', if provided\n        layers (Dict[str, dict]): prettymaps.plot() 'layers' parameter dict\n        style (Dict[str, dict]): prettymaps.plot() 'style' parameter dict\n        circle (Optional[bool]): prettymaps.plot() 'circle' parameter\n        radius (Optional[Union[float, bool]]): prettymaps.plot() 'radius' parameter\n        dilate (Optional[Union[float, bool]]): prettymaps.plot() 'dilate' parameter\n\n    Returns:\n        Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]]: Updated layers, style, circle, radius, dilate parameters\n    \"\"\"\n\n    # Update preset mode: load a preset, update it with additional parameters and update the JSON file\n    if update_preset is not None:\n        # load_preset = save_preset = True\n        load_preset = save_preset = update_preset\n\n    # Load preset (if provided)\n    if load_preset is not None:\n        layers, style, circle, radius, dilate = override_preset(\n            load_preset, layers, style, circle, radius, dilate\n        )\n\n    # Save parameters as preset\n    if save_preset is not None:\n        create_preset(\n            save_preset,\n            layers=layers,\n            style=style,\n            circle=circle,\n            radius=radius,\n            dilate=dilate,\n        )\n\n    return layers, style, circle, radius, dilate\n
"},{"location":"api/#prettymaps.draw.multiplot","title":"multiplot(*subplots, figsize=None, credit={}, **kwargs)","text":"

Creates a multiplot using the provided subplots and optional parameters.

"},{"location":"api/#prettymaps.draw.multiplot--parameters","title":"Parameters:","text":"

subplots : list A list of subplot objects to be plotted. figsize : tuple, optional A tuple specifying the figure size (width, height) in inches. credit : dict, optional A dictionary containing credit information for the plot. *kwargs : dict, optional Additional keyword arguments to customize the plot.

"},{"location":"api/#prettymaps.draw.multiplot--returns","title":"Returns:","text":"

None

Source code in prettymaps/draw.py
def multiplot(*subplots, figsize=None, credit={}, **kwargs):\n    \"\"\"\n    Creates a multiplot using the provided subplots and optional parameters.\n\n    Parameters:\n    -----------\n    *subplots : list\n        A list of subplot objects to be plotted.\n    figsize : tuple, optional\n        A tuple specifying the figure size (width, height) in inches.\n    credit : dict, optional\n        A dictionary containing credit information for the plot.\n    **kwargs : dict, optional\n        Additional keyword arguments to customize the plot.\n\n    Returns:\n    --------\n    None\n    \"\"\"\n\n    fig = plt.figure(figsize=figsize)\n    ax = plt.subplot(111, aspect=\"equal\")\n\n    mode = \"plotter\" if \"plotter\" in kwargs and kwargs[\"plotter\"] else \"matplotlib\"\n\n    subplots_results = [\n        plot(\n            subplot.query,\n            ax=ax,\n            multiplot=True,\n            **override_params(\n                subplot.kwargs,\n                {\n                    k: v\n                    for k, v in kwargs.items()\n                    if k != \"load_preset\" or \"load_preset\" not in subplot.kwargs\n                },\n            ),\n            show=False,\n        )\n        for subplot in subplots\n    ]\n\n    if mode == \"matplotlib\":\n        ax.axis(\"off\")\n        ax.axis(\"equal\")\n        ax.autoscale()\n
"},{"location":"api/#prettymaps.draw.override_args","title":"override_args(layers, circle, dilate, logging=False)","text":"

Override arguments in layers' kwargs

Parameters:

Name Type Description Default layers dict

prettymaps.plot() Layers parameters dict

required circle Optional[bool]

prettymaps.plot() 'Circle' parameter

required dilate Optional[Union[float, bool]]

prettymaps.plot() 'dilate' parameter

required

Returns:

Name Type Description dict dict

output dict

Source code in prettymaps/draw.py
@log_execution_time\ndef override_args(\n    layers: dict,\n    circle: Optional[bool],\n    dilate: Optional[Union[float, bool]],\n    logging=False,\n) -> dict:\n    \"\"\"\n    Override arguments in layers' kwargs\n\n    Args:\n        layers (dict): prettymaps.plot() Layers parameters dict\n        circle (Optional[bool]): prettymaps.plot() 'Circle' parameter\n        dilate (Optional[Union[float, bool]]): prettymaps.plot() 'dilate' parameter\n\n    Returns:\n        dict: output dict\n    \"\"\"\n    override_args = [\"circle\", \"dilate\"]\n    for layer in layers:\n        for arg in override_args:\n            if arg not in layers[layer]:\n                layers[layer][arg] = locals()[arg]\n    return layers\n
"},{"location":"api/#prettymaps.draw.override_params","title":"override_params(default_dict, new_dict)","text":"

Override parameters in 'default_dict' with additional parameters from 'new_dict'

Parameters:

Name Type Description Default default_dict dict

Default dict to be overriden with 'new_dict' parameters

required new_dict dict

New dict to override 'default_dict' parameters

required

Returns:

Name Type Description dict dict

default_dict overriden with new_dict parameters

Source code in prettymaps/draw.py
def override_params(default_dict: dict, new_dict: dict) -> dict:\n    \"\"\"\n    Override parameters in 'default_dict' with additional parameters from 'new_dict'\n\n    Args:\n        default_dict (dict): Default dict to be overriden with 'new_dict' parameters\n        new_dict (dict): New dict to override 'default_dict' parameters\n\n    Returns:\n        dict: default_dict overriden with new_dict parameters\n    \"\"\"\n\n    final_dict = deepcopy(default_dict)\n\n    for key in new_dict.keys():\n        if type(new_dict[key]) == dict:\n            if key in final_dict:\n                final_dict[key] = override_params(final_dict[key], new_dict[key])\n            else:\n                final_dict[key] = new_dict[key]\n        else:\n            final_dict[key] = new_dict[key]\n\n    return final_dict\n
"},{"location":"api/#prettymaps.draw.override_preset","title":"override_preset(name, layers={}, style={}, circle=None, radius=None, dilate=None)","text":"

Read the preset file given by 'name' and override it with additional parameters

Parameters:

Name Type Description Default name str

description

required layers Dict[str, dict]

description. Defaults to {}.

{} style Dict[str, dict]

description. Defaults to {}.

{} circle Union[float, None]

description. Defaults to None.

None radius Union[float, None]

description. Defaults to None.

None dilate Union[float, None]

description. Defaults to None.

None

Returns:

Type Description Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]]

Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]]: Preset parameters overriden by additional provided parameters

Source code in prettymaps/draw.py
def override_preset(\n    name: str,\n    layers: Dict[str, dict] = {},\n    style: Dict[str, dict] = {},\n    circle: Optional[float] = None,\n    radius: Optional[Union[float, bool]] = None,\n    dilate: Optional[Union[float, bool]] = None,\n) -> Tuple[\n    dict,\n    dict,\n    Optional[float],\n    Optional[Union[float, bool]],\n    Optional[Union[float, bool]],\n]:\n    \"\"\"\n    Read the preset file given by 'name' and override it with additional parameters\n\n    Args:\n        name (str): _description_\n        layers (Dict[str, dict], optional): _description_. Defaults to {}.\n        style (Dict[str, dict], optional): _description_. Defaults to {}.\n        circle (Union[float, None], optional): _description_. Defaults to None.\n        radius (Union[float, None], optional): _description_. Defaults to None.\n        dilate (Union[float, None], optional): _description_. Defaults to None.\n\n    Returns:\n        Tuple[dict, dict, Optional[float], Optional[Union[float, bool]], Optional[Union[float, bool]]]: Preset parameters overriden by additional provided parameters\n    \"\"\"\n\n    params = read_preset(name)\n\n    # Override preset with kwargs\n    if \"layers\" in params:\n        layers = override_params(params[\"layers\"], layers)\n    if \"style\" in params:\n        style = override_params(params[\"style\"], style)\n    if circle is None and \"circle\" in params:\n        circle = params[\"circle\"]\n    if radius is None and \"radius\" in params:\n        radius = params[\"radius\"]\n    if dilate is None and \"dilate\" in params:\n        dilate = params[\"dilate\"]\n\n    # Delete layers marked as 'False' in the parameter dict\n    for layer in [key for key in layers.keys() if layers[key] == False]:\n        del layers[layer]\n\n    # Return overriden presets\n    return layers, style, circle, radius, dilate\n
"},{"location":"api/#prettymaps.draw.plot","title":"plot(query, layers={}, style={}, keypoints={}, preset='default', use_preset=True, save_preset=None, update_preset=None, postprocessing=lambda x: x, circle=None, radius=None, dilate=None, save_as=None, fig=None, ax=None, figsize=(11.7, 11.7), credit={}, mode='matplotlib', multiplot=False, show=True, x=0, y=0, scale_x=1, scale_y=1, rotation=0, logging=False, semantic=False, adjust_aspect_ratio=True)","text":"

Plots a map based on a given query and specified parameters. Args: query: The query for the location to plot. This can be a string (e.g., \"Porto Alegre\"), a tuple of latitude and longitude coordinates, or a custom GeoDataFrame boundary. layers: The OpenStreetMap layers to plot. Defaults to an empty dictionary. style: Matplotlib parameters for drawing each layer. Defaults to an empty dictionary. keypoints: Keypoints to highlight on the map. Defaults to an empty dictionary. preset: Preset configuration to use. Defaults to \"default\". use_preset: Whether to use the preset configuration. Defaults to True. save_preset: Path to save the preset configuration. Defaults to None. update_preset: Path to update the preset configuration with additional parameters. Defaults to None. circle: Whether to use a circular boundary. Defaults to None. radius: Radius for the circular or square boundary. Defaults to None. dilate: Amount to dilate the boundary. Defaults to None. save_as: Path to save the resulting plot. Defaults to None. fig: Matplotlib figure object. Defaults to None. ax: Matplotlib axes object. Defaults to None. title: Title of the plot. Defaults to None. figsize: Size of the figure. Defaults to (11.7, 11.7). constrained_layout: Whether to use constrained layout for the figure. Defaults to True. credit: Parameters for the credit message. Defaults to an empty dictionary. mode: Mode for plotting ('matplotlib' or 'plotter'). Defaults to \"matplotlib\". multiplot: Whether to use multiplot mode. Defaults to False. show: Whether to display the plot using matplotlib. Defaults to True. x: Translation parameter in the x direction. Defaults to 0. y: Translation parameter in the y direction. Defaults to 0. scale_x: Scaling parameter in the x direction. Defaults to 1. scale_y: Scaling parameter in the y direction. Defaults to 1. rotation: Rotation parameter in degrees. Defaults to 0. logging: Whether to enable logging. Defaults to False. Returns: Plot: The resulting plot object.

Source code in prettymaps/draw.py
def plot(\n    query: str | Tuple[float, float] | gp.GeoDataFrame,\n    layers: Dict[str, Dict[str, Any]] = {},\n    style: Dict[str, Dict[str, Any]] = {},\n    keypoints: Dict[str, Any] = {},\n    preset: str = \"default\",\n    use_preset: bool = True,\n    save_preset: str | None = None,\n    update_preset: str | None = None,\n    postprocessing: Callable[\n        [Dict[str, gp.GeoDataFrame]], Dict[str, gp.GeoDataFrame]\n    ] = lambda x: x,\n    circle: bool | None = None,\n    radius: float | bool | None = None,\n    dilate: float | bool | None = None,\n    save_as: str | None = None,\n    fig: plt.Figure | None = None,\n    ax: plt.Axes | None = None,\n    figsize: Tuple[float, float] = (11.7, 11.7),\n    credit: Dict[str, Any] = {},\n    mode: str = \"matplotlib\",\n    multiplot: bool = False,\n    show: bool = True,\n    x: float = 0,\n    y: float = 0,\n    scale_x: float = 1,\n    scale_y: float = 1,\n    rotation: float = 0,\n    logging: bool = False,\n    semantic: bool = False,\n    adjust_aspect_ratio: bool = True,\n) -> Plot:\n    \"\"\"\n    Plots a map based on a given query and specified parameters.\n    Args:\n        query: The query for the location to plot. This can be a string (e.g., \"Porto Alegre\"), a tuple of latitude and longitude coordinates, or a custom GeoDataFrame boundary.\n        layers: The OpenStreetMap layers to plot. Defaults to an empty dictionary.\n        style: Matplotlib parameters for drawing each layer. Defaults to an empty dictionary.\n        keypoints: Keypoints to highlight on the map. Defaults to an empty dictionary.\n        preset: Preset configuration to use. Defaults to \"default\".\n        use_preset: Whether to use the preset configuration. Defaults to True.\n        save_preset: Path to save the preset configuration. Defaults to None.\n        update_preset: Path to update the preset configuration with additional parameters. Defaults to None.\n        circle: Whether to use a circular boundary. Defaults to None.\n        radius: Radius for the circular or square boundary. Defaults to None.\n        dilate: Amount to dilate the boundary. Defaults to None.\n        save_as: Path to save the resulting plot. Defaults to None.\n        fig: Matplotlib figure object. Defaults to None.\n        ax: Matplotlib axes object. Defaults to None.\n        title: Title of the plot. Defaults to None.\n        figsize: Size of the figure. Defaults to (11.7, 11.7).\n        constrained_layout: Whether to use constrained layout for the figure. Defaults to True.\n        credit: Parameters for the credit message. Defaults to an empty dictionary.\n        mode: Mode for plotting ('matplotlib' or 'plotter'). Defaults to \"matplotlib\".\n        multiplot: Whether to use multiplot mode. Defaults to False.\n        show: Whether to display the plot using matplotlib. Defaults to True.\n        x: Translation parameter in the x direction. Defaults to 0.\n        y: Translation parameter in the y direction. Defaults to 0.\n        scale_x: Scaling parameter in the x direction. Defaults to 1.\n        scale_y: Scaling parameter in the y direction. Defaults to 1.\n        rotation: Rotation parameter in degrees. Defaults to 0.\n        logging: Whether to enable logging. Defaults to False.\n    Returns:\n        Plot: The resulting plot object.\n    \"\"\"\n\n    # 1. Manage presets\n    layers, style, circle, radius, dilate = manage_presets(\n        preset if use_preset else None,\n        save_preset,\n        update_preset,\n        layers,\n        style,\n        circle,\n        radius,\n        dilate,\n    )\n\n    # 2. Init matplotlib figure & axis and vsketch object\n    fig, ax, vsk = init_plot(\n        layers,\n        fig,\n        ax,\n        figsize,\n        mode,\n        adjust_aspect_ratio=adjust_aspect_ratio,\n        logging=logging,\n    )\n\n    # 3. Override arguments in layers' kwargs dict\n    layers = override_args(layers, circle, dilate, logging=logging)\n\n    # 4. Fetch geodataframes\n    start_time = time.time()\n    gdfs = get_gdfs(query, layers, radius, dilate, -rotation, logging=logging)\n    fetch_time = time.time() - start_time\n    print(f\"Fetching geodataframes took {fetch_time:.2f} seconds\")\n\n    # 5. Apply transformations to GeoDataFrames (translation, scale, rotation)\n    gdfs = transform_gdfs(gdfs, x, y, scale_x, scale_y, rotation, logging=logging)\n\n    # 6. Apply a postprocessing function to the GeoDataFrames, if provided\n    gdfs = postprocessing(gdfs)\n\n    # 7. Create background GeoDataFrame and get (x,y) bounds\n    background, xmin, ymin, xmax, ymax, dx, dy = create_background(\n        gdfs, style, logging=logging\n    )\n\n    # 8. Draw layers\n    draw_layers(layers, gdfs, style, fig, ax, vsk, mode, logging=logging)\n\n    # 9. Draw keypoints\n    keypoints = draw_keypoints(keypoints, gdfs, ax, logging=logging)\n\n    # 9. Draw background\n    draw_background(background, ax, style, mode, logging=logging)\n\n    # 10. Draw credit message\n    draw_credit(ax, background, credit, mode, multiplot, logging=logging)\n\n    # 11. Draw hillshade\n    draw_hillshade(\n        layers,\n        gdfs,\n        ax,\n        logging=logging,\n        **(layers[\"hillshade\"] if \"hillshade\" in layers else {}),\n    )\n\n    # 12. Create Plot object\n    plot = Plot(gdfs, fig, ax, background, keypoints)\n\n    # 13. Save plot as image\n    if save_as is not None:\n        plt.savefig(save_as)\n\n    # 14. Show plot\n    if show:\n        if mode == \"plotter\":\n            vsk.display()\n        elif mode == \"matplotlib\":\n            plt.show()\n        else:\n            raise Exception(f\"Unknown mode {mode}\")\n    else:\n        plt.close()\n\n    return plot\n
"},{"location":"api/#prettymaps.draw.plot_gdf","title":"plot_gdf(layer, gdf, ax, mode='matplotlib', vsk=None, palette=None, width=None, union=False, dilate_points=None, dilate_lines=None, **kwargs)","text":"

Plot a layer

Parameters:

Name Type Description Default layer str

layer name

required gdf GeoDataFrame

GeoDataFrame

required ax Axes

matplotlib axis object

required mode str

drawing mode. Options: 'matplotlib', 'vsketch'. Defaults to 'matplotlib'

'matplotlib' vsk Optional[SketchClass]

Vsketch object. Mandatory if mode == 'plotter'

None palette Optional[List[str]]

Color palette. Defaults to None.

None width Optional[Union[dict, float]]

Street widths. Either a dictionary or a float. Defaults to None.

None union bool

Whether to join geometries. Defaults to False.

False dilate_points Optional[float]

Amount of dilation to be applied to point (1D) geometries. Defaults to None.

None dilate_lines Optional[float]

Amount of dilation to be applied to line (2D) geometries. Defaults to None.

None

Raises:

Type Description Exception

description

Source code in prettymaps/draw.py
def plot_gdf(\n    layer: str,\n    gdf: gp.GeoDataFrame,\n    ax: matplotlib.axes.Axes,\n    mode: str = \"matplotlib\",\n    # vsk: Optional[vsketch.SketchClass] = None,\n    vsk=None,\n    palette: Optional[List[str]] = None,\n    width: Optional[Union[dict, float]] = None,\n    union: bool = False,\n    dilate_points: Optional[float] = None,\n    dilate_lines: Optional[float] = None,\n    **kwargs,\n) -> None:\n    \"\"\"\n    Plot a layer\n\n    Args:\n        layer (str): layer name\n        gdf (gp.GeoDataFrame): GeoDataFrame\n        ax (matplotlib.axes.Axes): matplotlib axis object\n        mode (str): drawing mode. Options: 'matplotlib', 'vsketch'. Defaults to 'matplotlib'\n        vsk (Optional[vsketch.SketchClass]): Vsketch object. Mandatory if mode == 'plotter'\n        palette (Optional[List[str]], optional): Color palette. Defaults to None.\n        width (Optional[Union[dict, float]], optional): Street widths. Either a dictionary or a float. Defaults to None.\n        union (bool, optional): Whether to join geometries. Defaults to False.\n        dilate_points (Optional[float], optional): Amount of dilation to be applied to point (1D) geometries. Defaults to None.\n        dilate_lines (Optional[float], optional): Amount of dilation to be applied to line (2D) geometries. Defaults to None.\n\n    Raises:\n        Exception: _description_\n    \"\"\"\n\n    # Get hatch and hatch_c parameter\n    hatch_c = kwargs.pop(\"hatch_c\") if \"hatch_c\" in kwargs else None\n\n    # Convert GDF to shapely geometries\n    geometries = gdf_to_shapely(\n        layer, gdf, width, point_size=dilate_points, line_width=dilate_lines\n    )\n\n    # Unite geometries\n    if union:\n        geometries = shapely.ops.unary_union(GeometryCollection([geometries]))\n\n    if (palette is None) and (\"fc\" in kwargs) and (type(kwargs[\"fc\"]) != str):\n        palette = kwargs.pop(\"fc\")\n\n    for shape in geometries.geoms if hasattr(geometries, \"geoms\") else [geometries]:\n        if mode == \"matplotlib\":\n            if type(shape) in [Polygon, MultiPolygon]:\n                # Plot main shape (without silhouette)\n                ax.add_patch(\n                    PolygonPatch(\n                        shape,\n                        lw=0,\n                        ec=(\n                            hatch_c\n                            if hatch_c\n                            else kwargs[\"ec\"] if \"ec\" in kwargs else None\n                        ),\n                        fc=(\n                            kwargs[\"fc\"]\n                            if \"fc\" in kwargs\n                            else np.random.choice(palette) if palette else None\n                        ),\n                        **{\n                            k: v\n                            for k, v in kwargs.items()\n                            if k not in [\"lw\", \"ec\", \"fc\"]\n                        },\n                    ),\n                )\n                # Plot just silhouette\n                ax.add_patch(\n                    PolygonPatch(\n                        shape,\n                        fill=False,\n                        **{\n                            k: v\n                            for k, v in kwargs.items()\n                            if k not in [\"hatch\", \"fill\"]\n                        },\n                    )\n                )\n            elif type(shape) == LineString:\n                ax.plot(\n                    *shape.xy,\n                    c=kwargs[\"ec\"] if \"ec\" in kwargs else None,\n                    **{\n                        k: v\n                        for k, v in kwargs.items()\n                        if k in [\"lw\", \"ls\", \"dashes\", \"zorder\"]\n                    },\n                )\n            elif type(shape) == MultiLineString:\n                for c in shape.geoms:\n                    ax.plot(\n                        *c.xy,\n                        c=kwargs[\"ec\"] if \"ec\" in kwargs else None,\n                        **{\n                            k: v\n                            for k, v in kwargs.items()\n                            if k in [\"lw\", \"lt\", \"dashes\", \"zorder\"]\n                        },\n                    )\n        elif mode == \"plotter\":\n            if (\"draw\" not in kwargs) or kwargs[\"draw\"]:\n\n                # Set stroke\n                if \"stroke\" in kwargs:\n                    vsk.stroke(kwargs[\"stroke\"])\n                else:\n                    vsk.stroke(1)\n\n                # Set pen width\n                if \"penWidth\" in kwargs:\n                    vsk.penWidth(kwargs[\"penWidth\"])\n                else:\n                    vsk.penWidth(0.3)\n\n                if \"fill\" in kwargs:\n                    vsk.fill(kwargs[\"fill\"])\n                else:\n                    vsk.noFill()\n\n                vsk.geometry(shape)\n        else:\n            raise Exception(f\"Unknown mode {mode}\")\n
"},{"location":"api/#prettymaps.draw.presets_directory","title":"presets_directory()","text":"

Returns the path to the 'presets' directory. This function constructs the path to the 'presets' directory, which is located in the same directory as the current script file. Returns: str: The full path to the 'presets' directory.

Source code in prettymaps/draw.py
def presets_directory():\n    \"\"\"\n    Returns the path to the 'presets' directory.\n    This function constructs the path to the 'presets' directory, which is\n    located in the same directory as the current script file.\n    Returns:\n        str: The full path to the 'presets' directory.\n    \"\"\"\n\n    return os.path.join(pathlib.Path(__file__).resolve().parent, \"presets\")\n
"},{"location":"api/#prettymaps.draw.read_preset","title":"read_preset(name)","text":"

Read a preset from the presets folder (prettymaps/presets/)

Parameters:

Name Type Description Default name str

Preset name

required

Returns:

Type Description Dict[str, dict]

parameters dictionary

Source code in prettymaps/draw.py
def read_preset(name: str) -> Dict[str, dict]:\n    \"\"\"\n    Read a preset from the presets folder (prettymaps/presets/)\n\n    Args:\n        name (str): Preset name\n\n    Returns:\n        (Dict[str,dict]): parameters dictionary\n    \"\"\"\n    path = os.path.join(presets_directory(), f\"{name}.json\")\n    with open(path, \"r\") as f:\n        # Load params from JSON file\n        params = json.load(f)\n    return params\n
"},{"location":"api/#prettymaps.draw.transform_gdfs","title":"transform_gdfs(gdfs, x=0, y=0, scale_x=1, scale_y=1, rotation=0, logging=False)","text":"

Apply geometric transformations to dictionary of GeoDataFrames

Parameters:

Name Type Description Default gdfs Dict[str, GeoDataFrame]

Dictionary of GeoDataFrames

required x float

x-axis translation. Defaults to 0.

0 y float

y-axis translation. Defaults to 0.

0 scale_x float

x-axis scale. Defaults to 1.

1 scale_y float

y-axis scale. Defaults to 1.

1 rotation float

rotation angle (in radians). Defaults to 0.

0

Returns:

Type Description Dict[str, GeoDataFrame]

Dict[str, gp.GeoDataFrame]: dictionary of transformed GeoDataFrames

Source code in prettymaps/draw.py
@log_execution_time\ndef transform_gdfs(\n    gdfs: Dict[str, gp.GeoDataFrame],\n    x: float = 0,\n    y: float = 0,\n    scale_x: float = 1,\n    scale_y: float = 1,\n    rotation: float = 0,\n    logging=False,\n) -> Dict[str, gp.GeoDataFrame]:\n    \"\"\"\n    Apply geometric transformations to dictionary of GeoDataFrames\n\n    Args:\n        gdfs (Dict[str, gp.GeoDataFrame]): Dictionary of GeoDataFrames\n        x (float, optional): x-axis translation. Defaults to 0.\n        y (float, optional): y-axis translation. Defaults to 0.\n        scale_x (float, optional): x-axis scale. Defaults to 1.\n        scale_y (float, optional): y-axis scale. Defaults to 1.\n        rotation (float, optional): rotation angle (in radians). Defaults to 0.\n\n    Returns:\n        Dict[str, gp.GeoDataFrame]: dictionary of transformed GeoDataFrames\n    \"\"\"\n    # Project geometries\n    gdfs = {\n        name: ox.project_gdf(gdf) if len(gdf) > 0 else gdf for name, gdf in gdfs.items()\n    }\n    # Create geometry collection from gdfs' geometries\n    collection = GeometryCollection(\n        [GeometryCollection(list(gdf.geometry)) for gdf in gdfs.values()]\n    )\n    # Translation, scale & rotation\n    collection = shapely.affinity.translate(collection, x, y)\n    collection = shapely.affinity.scale(collection, scale_x, scale_y)\n    collection = shapely.affinity.rotate(collection, rotation)\n    # Update geometries\n    for i, layer in enumerate(gdfs):\n        gdfs[layer].geometry = list(collection.geoms[i].geoms)\n        # Reproject\n        if len(gdfs[layer]) > 0:\n            gdfs[layer] = ox.project_gdf(gdfs[layer], to_crs=\"EPSG:4326\")\n\n    return gdfs\n
"},{"location":"api/#prettymaps.fetch","title":"prettymaps.fetch","text":"

Prettymaps - A minimal Python library to draw pretty maps from OpenStreetMap Data Copyright (C) 2021 Marcelo Prates

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.

"},{"location":"api/#prettymaps.fetch.get_keypoints","title":"get_keypoints(perimeter, tags={'place': 'quarter', 'highway': True, 'building': True, 'landuse': True, 'natural': True, 'waterway': True, 'amenity': True, 'leisure': True, 'shop': True, 'public_transport': True, 'tourism': True, 'historic': True, 'barrier': True, 'power': True, 'railway': True, 'cycleway': True, 'footway': True, 'healthcare': True, 'office': True, 'craft': True, 'man_made': True, 'boundary': True})","text":"

Extract keypoints from a given perimeter based on specified tags.

Parameters: perimeter (shapely.geometry.Polygon): The polygon representing the area of interest. tags (dict, optional): A dictionary of tags to filter the keypoints. The keys are tag names and the values are booleans indicating whether to include the tag. Default includes a variety of common tags.

Returns: geopandas.GeoDataFrame: A GeoDataFrame containing the keypoints that match the specified tags within the given perimeter.

Source code in prettymaps/fetch.py
def get_keypoints(\n    perimeter,\n    tags={\n        \"place\": \"quarter\",\n        \"highway\": True,\n        \"building\": True,\n        \"landuse\": True,\n        \"natural\": True,\n        \"waterway\": True,\n        \"amenity\": True,\n        \"leisure\": True,\n        \"shop\": True,\n        \"public_transport\": True,\n        \"tourism\": True,\n        \"historic\": True,\n        \"barrier\": True,\n        \"power\": True,\n        \"railway\": True,\n        \"cycleway\": True,\n        \"footway\": True,\n        \"healthcare\": True,\n        \"office\": True,\n        \"craft\": True,\n        \"man_made\": True,\n        \"boundary\": True,\n    },\n):\n    \"\"\"\n    Extract keypoints from a given perimeter based on specified tags.\n\n    Parameters:\n    perimeter (shapely.geometry.Polygon): The polygon representing the area of interest.\n    tags (dict, optional): A dictionary of tags to filter the keypoints. The keys are tag names and the values are booleans indicating whether to include the tag. Default includes a variety of common tags.\n\n    Returns:\n    geopandas.GeoDataFrame: A GeoDataFrame containing the keypoints that match the specified tags within the given perimeter.\n    \"\"\"\n    keypoints_df = ox.features_from_polygon(perimeter, tags=tags)\n\n    return keypoints_df\n
"},{"location":"api/#prettymaps.fetch.merge_tags","title":"merge_tags(layers_dict)","text":"

Merge tags from a dictionary of layers into a single dictionary.

Parameters: layers_dict (dict): Dictionary of layers with their respective tags.

Returns: dict: Merged dictionary of tags.

Source code in prettymaps/fetch.py
def merge_tags(layers_dict: dict) -> dict:\n    \"\"\"\n    Merge tags from a dictionary of layers into a single dictionary.\n\n    Parameters:\n    layers_dict (dict): Dictionary of layers with their respective tags.\n\n    Returns:\n    dict: Merged dictionary of tags.\n    \"\"\"\n\n    layers_dict = deepcopy(layers_dict)\n    merged_tags = {}\n\n    def _merge(d: dict):\n        for key, value in d.items():\n            if isinstance(value, dict):\n                if \"tags\" in value:\n                    for tag_key, tag_value in value[\"tags\"].items():\n                        if tag_key in merged_tags:\n                            if isinstance(merged_tags[tag_key], list):\n                                if isinstance(tag_value, list):\n                                    merged_tags[tag_key].extend(tag_value)\n                                else:\n                                    merged_tags[tag_key].append(tag_value)\n                            else:\n                                merged_tags[tag_key] = (\n                                    [merged_tags[tag_key], tag_value]\n                                    if not isinstance(tag_value, list)\n                                    else [merged_tags[tag_key]] + tag_value\n                                )\n                        else:\n                            merged_tags[tag_key] = (\n                                tag_value\n                                if isinstance(tag_value, list)\n                                else [tag_value]\n                            )\n                _merge(value)\n\n    _merge(layers_dict)\n\n    # Simplify lists with a single element\n    merged_tags = {\n        k: (v[0] if isinstance(v, list) and len(v) == 1 else v)\n        for k, v in merged_tags.items()\n    }\n\n    return merged_tags\n
"},{"location":"api/#prettymaps.fetch.obtain_elevation","title":"obtain_elevation(gdf)","text":"

Download all SRTM elevation tiles for the given polygon in a GeoDataFrame.

Parameters: gdf (GeoDataFrame): GeoDataFrame containing the polygon. output_dir (str): Directory to save the downloaded tiles.

Source code in prettymaps/fetch.py
def obtain_elevation(gdf):\n    \"\"\"\n    Download all SRTM elevation tiles for the given polygon in a GeoDataFrame.\n\n    Parameters:\n    gdf (GeoDataFrame): GeoDataFrame containing the polygon.\n    output_dir (str): Directory to save the downloaded tiles.\n    \"\"\"\n\n    # Ensure the GeoDataFrame has a single polygon\n    if len(gdf) != 1:\n        raise ValueError(\"GeoDataFrame must contain a single polygon\")\n\n    with warnings.catch_warnings():\n        warnings.simplefilter(\"ignore\")\n        subprocess.run(\n            [\"eio\", \"clean\"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL\n        )\n\n    # Get the bounding box of the polygon\n    bounds = gdf.total_bounds\n    min_lon, min_lat, max_lon, max_lat = bounds\n\n    # Configure the bounding box for the elevation library\n\n    output_file = os.path.join(os.getcwd(), \"elevation.tif\")\n    elevation.clip(\n        bounds=(min_lon, min_lat, max_lon, max_lat),\n        output=output_file,\n        margin=\"10%\",\n        cache_dir=\".\",\n    )\n\n    # subprocess.run(\n    #    [\n    #        \"gdalwarp\",\n    #        \"-tr\",\n    #        \"30\",\n    #        \"30\",\n    #        \"-r\",\n    #        \"cubic\",\n    #        \"elevation.tif\",\n    #        \"resampled_elevation.tif\",\n    #    ],\n    #    # stdout=subprocess.DEVNULL,\n    #    # stderr=subprocess.DEVNULL,\n    # )\n\n    raster = rxr.open_rasterio(output_file).squeeze()\n\n    raster = raster.rio.reproject(CRS.from_string(ox.project_gdf(gdf).crs.to_string()))\n\n    # convert to numpy array\n    elevation_data = raster.data\n\n    return elevation_data\n
"},{"location":"api/#prettymaps.fetch.read_from_cache","title":"read_from_cache(perimeter, layer_kwargs, cache_dir='prettymaps_cache')","text":"

Read a GeoDataFrame from the cache based on the perimeter and layer arguments.

Parameters: perimeter (GeoDataFrame): The perimeter GeoDataFrame. layer_kwargs (dict): Dictionary of layer arguments. cache_dir (str): Directory to read the cached GeoDataFrame from.

Returns: GeoDataFrame: The cached GeoDataFrame, or None if it does not exist.

Source code in prettymaps/fetch.py
def read_from_cache(\n    perimeter: GeoDataFrame,\n    layer_kwargs: dict,\n    cache_dir: str = \"prettymaps_cache\",\n) -> GeoDataFrame:\n    \"\"\"\n    Read a GeoDataFrame from the cache based on the perimeter and layer arguments.\n\n    Parameters:\n    perimeter (GeoDataFrame): The perimeter GeoDataFrame.\n    layer_kwargs (dict): Dictionary of layer arguments.\n    cache_dir (str): Directory to read the cached GeoDataFrame from.\n\n    Returns:\n    GeoDataFrame: The cached GeoDataFrame, or None if it does not exist.\n    \"\"\"\n    np.random.seed(0)\n    # Create hash from perimeter\n    perimeter_hash = hash(perimeter[\"geometry\"].to_json())\n    # Create hash from kwargs\n    kwargs_hash = hash(str(layer_kwargs))\n    # Join hashes\n    hash_str = f\"{perimeter_hash}_{kwargs_hash}\"\n\n    cache_path = os.path.join(cache_dir, f\"{hash_str}.geojson\")\n\n    # Check if the gdf is cached\n    if os.path.exists(cache_path):\n        # Read cached gdf\n        return gp.read_file(cache_path)\n    else:\n        return None\n
"},{"location":"api/#prettymaps.fetch.unified_osm_request","title":"unified_osm_request(perimeter, layers_dict, logging=False)","text":"

Unify all OSM requests into one to improve efficiency.

Parameters: perimeter (GeoDataFrame): The perimeter GeoDataFrame. layers_dict (dict): Dictionary of layers to fetch. logging (bool): Enable or disable logging.

Returns: dict: Dictionary of GeoDataFrames for each layer.

Source code in prettymaps/fetch.py
def unified_osm_request(\n    perimeter: GeoDataFrame, layers_dict: dict, logging: bool = False\n) -> dict:\n    \"\"\"\n    Unify all OSM requests into one to improve efficiency.\n\n    Parameters:\n    perimeter (GeoDataFrame): The perimeter GeoDataFrame.\n    layers_dict (dict): Dictionary of layers to fetch.\n    logging (bool): Enable or disable logging.\n\n    Returns:\n    dict: Dictionary of GeoDataFrames for each layer.\n    \"\"\"\n    # Apply tolerance to the perimeter\n    perimeter_with_tolerance = ox.project_gdf(perimeter).buffer(0).to_crs(4326)\n    perimeter_with_tolerance = unary_union(perimeter_with_tolerance.geometry).buffer(0)\n\n    # Fetch from perimeter's bounding box, to avoid missing some geometries\n    bbox = box(*perimeter_with_tolerance.bounds)\n\n    # Initialize the result dictionary\n    gdfs = {}\n    ## Read layers from cache\n    # for layer, kwargs in layers_dict.items():\n    #    gdf = read_from_cache(perimeter, layers_dict[layer])\n    #    if gdf is not None:\n    #        gdfs[layer] = gdf\n\n    # Combine all tags into a single dictionary for a unified request\n    combined_tags = merge_tags(\n        {layer: kwargs for layer, kwargs in layers_dict.items() if layer not in gdfs}\n    )\n\n    # Fetch all features in one request\n    try:\n        all_features = ox.features_from_polygon(bbox, tags=combined_tags)\n    except Exception as e:\n        all_features = GeoDataFrame(geometry=[])\n\n    # Split the features into separate GeoDataFrames based on the layers_dict\n    for layer, kwargs in layers_dict.items():\n        if layer in gdfs:\n            continue\n        try:\n            if layer in [\"streets\", \"railway\", \"waterway\"]:\n                graph = ox.graph_from_polygon(\n                    bbox,\n                    custom_filter=kwargs.get(\"custom_filter\"),\n                    truncate_by_edge=True,\n                )\n                gdf = ox.graph_to_gdfs(graph, nodes=False)\n            elif layer == \"sea\":\n                try:\n                    coastline = unary_union(\n                        ox.features_from_polygon(\n                            bbox, tags={\"natural\": \"coastline\"}\n                        ).geometry.tolist()\n                    )\n                    sea_candidates = bbox.difference(coastline.buffer(1e-9)).geoms\n                    drive = ox.graph_from_polygon(bbox, network_type=\"drive\")\n                    drive = ox.graph_to_gdfs(drive, nodes=False)\n\n                    def filter_candidate(sea_candidate):\n                        intersections = drive.geometry.intersects(sea_candidate)\n                        if \"bridge\" in drive.columns:\n                            return not any(\n                                intersections\n                                & (\n                                    drive.loc[\n                                        drive.geometry.intersects(sea_candidate),\n                                        \"bridge\",\n                                    ]\n                                    != \"yes\"\n                                )\n                            )\n                        else:\n                            return not any(intersections)\n\n                    sea = unary_union(\n                        MultiPolygon(\n                            [\n                                candidate\n                                for candidate in sea_candidates\n                                if filter_candidate(candidate)\n                            ]\n                        ).geoms\n                    ).buffer(1e-8)\n                    gdf = GeoDataFrame(geometry=[sea], crs=perimeter.crs)\n                except:\n                    gdf = GeoDataFrame(geometry=[], crs=perimeter.crs)\n            else:\n                if kwargs.get(\"osmid\") is None:\n                    if layer == \"perimeter\":\n                        gdf = perimeter\n                    else:\n                        layer_tags = kwargs.get(\"tags\")\n                        gdf = gp.GeoDataFrame(geometry=[], crs=perimeter.crs)\n                        for key, value in layer_tags.items():\n                            if isinstance(value, bool) and value:\n                                filtered_features = all_features[\n                                    ~pd.isna(all_features[key])\n                                ]\n                            elif isinstance(value, list):\n                                filtered_features = all_features[\n                                    all_features[key].isin(value)\n                                ]\n                            else:\n                                filtered_features = all_features[\n                                    all_features[key] == value\n                                ]\n                            gdf = pd.concat([gdf, filtered_features], axis=0)\n                else:\n                    gdf = ox.geocode_to_gdf(kwargs.get(\"osmid\"), by_osmid=True)\n\n            gdf = gdf.copy()\n            gdf.geometry = gdf.geometry.intersection(perimeter_with_tolerance)\n            gdf.drop(gdf[gdf.geometry.is_empty].index, inplace=True)\n            gdfs[layer] = gdf\n            # write_to_cache(perimeter, gdf, layers_dict[layer])\n        except Exception as e:\n            # print(f\"Error fetching {layer}: {e}\")\n            gdfs[layer] = GeoDataFrame(geometry=[])\n\n    return gdfs\n
"},{"location":"api/#prettymaps.fetch.write_to_cache","title":"write_to_cache(perimeter, gdf, layer_kwargs, cache_dir='prettymaps_cache')","text":"

Write a GeoDataFrame to the cache based on the perimeter and layer arguments.

Parameters: perimeter (GeoDataFrame): The perimeter GeoDataFrame. gdf (GeoDataFrame): The GeoDataFrame to cache. layer_kwargs (dict): Dictionary of layer arguments. cache_dir (str): Directory to save the cached GeoDataFrame.

Source code in prettymaps/fetch.py
def write_to_cache(\n    perimeter: GeoDataFrame,\n    gdf: GeoDataFrame,\n    layer_kwargs: dict,\n    cache_dir: str = \"prettymaps_cache\",\n):\n    \"\"\"\n    Write a GeoDataFrame to the cache based on the perimeter and layer arguments.\n\n    Parameters:\n    perimeter (GeoDataFrame): The perimeter GeoDataFrame.\n    gdf (GeoDataFrame): The GeoDataFrame to cache.\n    layer_kwargs (dict): Dictionary of layer arguments.\n    cache_dir (str): Directory to save the cached GeoDataFrame.\n    \"\"\"\n    np.random.seed(0)\n    os.makedirs(cache_dir, exist_ok=True)\n\n    # Create hash from perimeter\n    perimeter_hash = hash(perimeter[\"geometry\"].to_json())\n    # Create hash from kwargs\n    kwargs_hash = hash(str(layer_kwargs))\n    # Join hashes\n    hash_str = f\"{perimeter_hash}_{kwargs_hash}\"\n\n    cache_path = os.path.join(cache_dir, f\"{hash_str}.geojson\")\n\n    # Write gdf to cache\n    logging.getLogger().setLevel(logging.CRITICAL)\n    if not gdf.empty:\n        gdf.to_file(cache_path, driver=\"GeoJSON\")\n    logging.getLogger().setLevel(logging.INFO)\n
"},{"location":"api/#prettymaps.utils","title":"prettymaps.utils","text":""},{"location":"usage/","title":"Usage","text":""},{"location":"usage/#basic-usage","title":"Basic Usage","text":"

The main entry point is the plot() function:

import prettymaps\nprettymaps.plot(\"Porto Alegre\")\n

This will generate a map for the given location using default layers and styles.

"},{"location":"usage/#customizing-layers-and-styles","title":"Customizing Layers and Styles","text":"

You can customize which OpenStreetMap layers are shown and how they are styled:

layers = {\n    \"perimeter\": {},\n    \"streets\": {\"width\": 8},\n    \"buildings\": {},\n}\nstyle = {\n    \"perimeter\": {\"fc\": \"#f2efe9\"},\n    \"streets\": {\"fc\": \"#cccccc\", \"ec\": \"#333333\"},\n    \"buildings\": {\"fc\": \"#bdbdbd\"},\n}\nprettymaps.plot(\"Porto Alegre\", layers=layers, style=style)\n
"},{"location":"usage/#using-presets","title":"Using Presets","text":"

Presets are reusable configurations for layers and styles. You can load, save, or update presets:

prettymaps.plot(\"Porto Alegre\", preset=\"default\")\n

You can also create your own presets and save them for later use.

"},{"location":"usage/#highlighting-keypoints","title":"Highlighting Keypoints","text":"

You can highlight specific keypoints (e.g., landmarks) on the map:

keypoints = {\n    \"tags\": {\"tourism\": \"attraction\"},\n    \"kwargs\": {\"bbox\": {\"fc\": \"yellow\"}},\n}\nprettymaps.plot(\"Porto Alegre\", keypoints=keypoints)\n
"},{"location":"usage/#saving-maps","title":"Saving Maps","text":"

You can save the generated map to a file:

prettymaps.plot(\"Porto Alegre\", save_as=\"map.png\")\n

See the API Reference for details on all functions and parameters.

"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Prettymaps Documentation","text":"

Welcome to the Prettymaps documentation site.

"},{"location":"api/","title":"API Reference","text":"

This page will contain the API reference for Prettymaps.

More details coming soon!

"},{"location":"usage/","title":"Usage","text":"

This page will describe how to use Prettymaps.

More details coming soon!

"}]} \ No newline at end of file diff --git a/usage/index.html b/usage/index.html index 769bf4a..f6ee42f 100644 --- a/usage/index.html +++ b/usage/index.html @@ -237,19 +237,6 @@ - - @@ -262,70 +249,6 @@ - - - - @@ -372,59 +295,6 @@ - - - @@ -440,45 +310,8 @@

Usage

-

Basic Usage

-

The main entry point is the plot() function:

-
import prettymaps
-prettymaps.plot("Porto Alegre")
-
-

This will generate a map for the given location using default layers and styles.

-

Customizing Layers and Styles

-

You can customize which OpenStreetMap layers are shown and how they are styled:

-
layers = {
-    "perimeter": {},
-    "streets": {"width": 8},
-    "buildings": {},
-}
-style = {
-    "perimeter": {"fc": "#f2efe9"},
-    "streets": {"fc": "#cccccc", "ec": "#333333"},
-    "buildings": {"fc": "#bdbdbd"},
-}
-prettymaps.plot("Porto Alegre", layers=layers, style=style)
-
-

Using Presets

-

Presets are reusable configurations for layers and styles. You can load, save, or update presets:

-
prettymaps.plot("Porto Alegre", preset="default")
-
-

You can also create your own presets and save them for later use.

-

Highlighting Keypoints

-

You can highlight specific keypoints (e.g., landmarks) on the map:

-
keypoints = {
-    "tags": {"tourism": "attraction"},
-    "kwargs": {"bbox": {"fc": "yellow"}},
-}
-prettymaps.plot("Porto Alegre", keypoints=keypoints)
-
-

Saving Maps

-

You can save the generated map to a file:

-
prettymaps.plot("Porto Alegre", save_as="map.png")
-
-
-

See the API Reference for details on all functions and parameters.

+

This page will describe how to use Prettymaps.

+

More details coming soon!