ssb-sgis 1.0.0__py3-none-any.whl → 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sgis/__init__.py +97 -115
- sgis/exceptions.py +3 -1
- sgis/geopandas_tools/__init__.py +1 -0
- sgis/geopandas_tools/bounds.py +75 -38
- sgis/geopandas_tools/buffer_dissolve_explode.py +38 -34
- sgis/geopandas_tools/centerlines.py +53 -44
- sgis/geopandas_tools/cleaning.py +87 -104
- sgis/geopandas_tools/conversion.py +149 -101
- sgis/geopandas_tools/duplicates.py +31 -17
- sgis/geopandas_tools/general.py +76 -48
- sgis/geopandas_tools/geometry_types.py +21 -7
- sgis/geopandas_tools/neighbors.py +20 -8
- sgis/geopandas_tools/overlay.py +136 -53
- sgis/geopandas_tools/point_operations.py +9 -8
- sgis/geopandas_tools/polygon_operations.py +48 -56
- sgis/geopandas_tools/polygons_as_rings.py +121 -78
- sgis/geopandas_tools/sfilter.py +14 -14
- sgis/helpers.py +114 -56
- sgis/io/dapla_functions.py +32 -23
- sgis/io/opener.py +13 -6
- sgis/io/read_parquet.py +1 -1
- sgis/maps/examine.py +39 -26
- sgis/maps/explore.py +112 -66
- sgis/maps/httpserver.py +12 -12
- sgis/maps/legend.py +124 -65
- sgis/maps/map.py +66 -41
- sgis/maps/maps.py +31 -29
- sgis/maps/thematicmap.py +46 -33
- sgis/maps/tilesources.py +3 -8
- sgis/networkanalysis/_get_route.py +5 -4
- sgis/networkanalysis/_od_cost_matrix.py +44 -1
- sgis/networkanalysis/_points.py +10 -4
- sgis/networkanalysis/_service_area.py +5 -2
- sgis/networkanalysis/closing_network_holes.py +20 -62
- sgis/networkanalysis/cutting_lines.py +55 -43
- sgis/networkanalysis/directednetwork.py +15 -7
- sgis/networkanalysis/finding_isolated_networks.py +4 -3
- sgis/networkanalysis/network.py +15 -13
- sgis/networkanalysis/networkanalysis.py +72 -54
- sgis/networkanalysis/networkanalysisrules.py +20 -16
- sgis/networkanalysis/nodes.py +2 -3
- sgis/networkanalysis/traveling_salesman.py +5 -2
- sgis/parallel/parallel.py +337 -127
- sgis/raster/__init__.py +6 -0
- sgis/raster/base.py +9 -3
- sgis/raster/cube.py +280 -208
- sgis/raster/cubebase.py +15 -29
- sgis/raster/indices.py +3 -7
- sgis/raster/methods_as_functions.py +0 -124
- sgis/raster/raster.py +313 -127
- sgis/raster/torchgeo.py +58 -37
- sgis/raster/zonal.py +38 -13
- {ssb_sgis-1.0.0.dist-info → ssb_sgis-1.0.2.dist-info}/LICENSE +1 -1
- {ssb_sgis-1.0.0.dist-info → ssb_sgis-1.0.2.dist-info}/METADATA +89 -18
- ssb_sgis-1.0.2.dist-info/RECORD +61 -0
- {ssb_sgis-1.0.0.dist-info → ssb_sgis-1.0.2.dist-info}/WHEEL +1 -1
- sgis/raster/bands.py +0 -48
- sgis/raster/gradient.py +0 -78
- ssb_sgis-1.0.0.dist-info/RECORD +0 -63
sgis/__init__.py
CHANGED
|
@@ -2,140 +2,120 @@ config = {
|
|
|
2
2
|
"n_jobs": 1,
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
import sgis.raster.bands as bands
|
|
6
5
|
import sgis.raster.indices as indices
|
|
7
|
-
from sgis.raster.raster import Raster
|
|
6
|
+
from sgis.raster.raster import Raster
|
|
7
|
+
from sgis.raster.raster import get_shape_from_bounds
|
|
8
|
+
from sgis.raster.raster import get_transform_from_bounds
|
|
8
9
|
|
|
9
|
-
from .geopandas_tools.bounds import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
from .geopandas_tools.buffer_dissolve_explode import
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
diss_by_cluster,
|
|
27
|
-
dissexp,
|
|
28
|
-
dissexp_by_cluster,
|
|
29
|
-
)
|
|
10
|
+
from .geopandas_tools.bounds import Gridlooper
|
|
11
|
+
from .geopandas_tools.bounds import bounds_to_points
|
|
12
|
+
from .geopandas_tools.bounds import bounds_to_polygon
|
|
13
|
+
from .geopandas_tools.bounds import get_total_bounds
|
|
14
|
+
from .geopandas_tools.bounds import gridloop
|
|
15
|
+
from .geopandas_tools.bounds import make_grid
|
|
16
|
+
from .geopandas_tools.bounds import make_grid_from_bbox
|
|
17
|
+
from .geopandas_tools.bounds import make_ssb_grid
|
|
18
|
+
from .geopandas_tools.bounds import points_in_bounds
|
|
19
|
+
from .geopandas_tools.buffer_dissolve_explode import buff
|
|
20
|
+
from .geopandas_tools.buffer_dissolve_explode import buffdiss
|
|
21
|
+
from .geopandas_tools.buffer_dissolve_explode import buffdissexp
|
|
22
|
+
from .geopandas_tools.buffer_dissolve_explode import buffdissexp_by_cluster
|
|
23
|
+
from .geopandas_tools.buffer_dissolve_explode import diss
|
|
24
|
+
from .geopandas_tools.buffer_dissolve_explode import diss_by_cluster
|
|
25
|
+
from .geopandas_tools.buffer_dissolve_explode import dissexp
|
|
26
|
+
from .geopandas_tools.buffer_dissolve_explode import dissexp_by_cluster
|
|
30
27
|
from .geopandas_tools.centerlines import get_rough_centerlines
|
|
31
|
-
from .geopandas_tools.cleaning import
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
from .geopandas_tools.conversion import
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
from .geopandas_tools.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
from .geopandas_tools.general import
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
from .geopandas_tools.
|
|
67
|
-
from .geopandas_tools.
|
|
68
|
-
|
|
69
|
-
is_single_geom_type,
|
|
70
|
-
make_all_singlepart,
|
|
71
|
-
to_single_geom_type,
|
|
72
|
-
)
|
|
73
|
-
from .geopandas_tools.neighbors import (
|
|
74
|
-
get_all_distances,
|
|
75
|
-
get_k_nearest_neighbors,
|
|
76
|
-
get_neighbor_dfs,
|
|
77
|
-
get_neighbor_indices,
|
|
78
|
-
k_nearest_neighbors,
|
|
79
|
-
sjoin_within_distance,
|
|
80
|
-
)
|
|
28
|
+
from .geopandas_tools.cleaning import coverage_clean
|
|
29
|
+
from .geopandas_tools.cleaning import remove_spikes
|
|
30
|
+
from .geopandas_tools.cleaning import split_and_eliminate_by_longest
|
|
31
|
+
from .geopandas_tools.cleaning import split_by_neighbors
|
|
32
|
+
from .geopandas_tools.conversion import coordinate_array
|
|
33
|
+
from .geopandas_tools.conversion import from_4326
|
|
34
|
+
from .geopandas_tools.conversion import to_4326
|
|
35
|
+
from .geopandas_tools.conversion import to_bbox
|
|
36
|
+
from .geopandas_tools.conversion import to_gdf
|
|
37
|
+
from .geopandas_tools.conversion import to_geoseries
|
|
38
|
+
from .geopandas_tools.conversion import to_shapely
|
|
39
|
+
from .geopandas_tools.duplicates import get_intersections # drop_duplicate_geometries,
|
|
40
|
+
from .geopandas_tools.duplicates import update_geometries # drop_duplicate_geometries,
|
|
41
|
+
from .geopandas_tools.general import _rename_geometry_if
|
|
42
|
+
from .geopandas_tools.general import clean_clip
|
|
43
|
+
from .geopandas_tools.general import clean_geoms
|
|
44
|
+
from .geopandas_tools.general import drop_inactive_geometry_columns
|
|
45
|
+
from .geopandas_tools.general import get_common_crs
|
|
46
|
+
from .geopandas_tools.general import get_grouped_centroids
|
|
47
|
+
from .geopandas_tools.general import random_points
|
|
48
|
+
from .geopandas_tools.general import random_points_in_polygons
|
|
49
|
+
from .geopandas_tools.general import sort_large_first
|
|
50
|
+
from .geopandas_tools.general import sort_long_first
|
|
51
|
+
from .geopandas_tools.general import sort_short_first
|
|
52
|
+
from .geopandas_tools.general import sort_small_first
|
|
53
|
+
from .geopandas_tools.general import to_lines
|
|
54
|
+
from .geopandas_tools.geocoding import address_to_coords
|
|
55
|
+
from .geopandas_tools.geocoding import address_to_gdf
|
|
56
|
+
from .geopandas_tools.geometry_types import get_geom_type
|
|
57
|
+
from .geopandas_tools.geometry_types import is_single_geom_type
|
|
58
|
+
from .geopandas_tools.geometry_types import make_all_singlepart
|
|
59
|
+
from .geopandas_tools.geometry_types import to_single_geom_type
|
|
60
|
+
from .geopandas_tools.neighbors import get_all_distances
|
|
61
|
+
from .geopandas_tools.neighbors import get_k_nearest_neighbors
|
|
62
|
+
from .geopandas_tools.neighbors import get_neighbor_dfs
|
|
63
|
+
from .geopandas_tools.neighbors import get_neighbor_indices
|
|
64
|
+
from .geopandas_tools.neighbors import k_nearest_neighbors
|
|
65
|
+
from .geopandas_tools.neighbors import sjoin_within_distance
|
|
81
66
|
from .geopandas_tools.overlay import clean_overlay
|
|
82
|
-
from .geopandas_tools.point_operations import snap_all
|
|
83
|
-
from .geopandas_tools.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
get_polygon_clusters,
|
|
95
|
-
)
|
|
67
|
+
from .geopandas_tools.point_operations import snap_all
|
|
68
|
+
from .geopandas_tools.point_operations import snap_within_distance
|
|
69
|
+
from .geopandas_tools.polygon_operations import close_all_holes
|
|
70
|
+
from .geopandas_tools.polygon_operations import close_small_holes
|
|
71
|
+
from .geopandas_tools.polygon_operations import close_thin_holes
|
|
72
|
+
from .geopandas_tools.polygon_operations import eliminate_by_largest
|
|
73
|
+
from .geopandas_tools.polygon_operations import eliminate_by_longest
|
|
74
|
+
from .geopandas_tools.polygon_operations import eliminate_by_smallest
|
|
75
|
+
from .geopandas_tools.polygon_operations import get_cluster_mapper
|
|
76
|
+
from .geopandas_tools.polygon_operations import get_gaps
|
|
77
|
+
from .geopandas_tools.polygon_operations import get_holes
|
|
78
|
+
from .geopandas_tools.polygon_operations import get_polygon_clusters
|
|
96
79
|
from .geopandas_tools.polygons_as_rings import PolygonsAsRings
|
|
97
|
-
from .geopandas_tools.sfilter import sfilter
|
|
98
|
-
from .
|
|
80
|
+
from .geopandas_tools.sfilter import sfilter
|
|
81
|
+
from .geopandas_tools.sfilter import sfilter_inverse
|
|
82
|
+
from .geopandas_tools.sfilter import sfilter_split
|
|
83
|
+
from .helpers import get_object_name
|
|
84
|
+
from .helpers import sort_nans_last
|
|
99
85
|
from .io.opener import opener
|
|
100
86
|
from .io.read_parquet import read_parquet_url
|
|
101
87
|
from .maps.examine import Examine
|
|
102
88
|
from .maps.explore import Explore
|
|
103
89
|
from .maps.httpserver import run_html_server
|
|
104
90
|
from .maps.legend import Legend
|
|
105
|
-
from .maps.maps import clipmap
|
|
91
|
+
from .maps.maps import clipmap
|
|
92
|
+
from .maps.maps import explore
|
|
93
|
+
from .maps.maps import explore_locals
|
|
94
|
+
from .maps.maps import qtm
|
|
95
|
+
from .maps.maps import samplemap
|
|
106
96
|
from .maps.thematicmap import ThematicMap
|
|
107
97
|
from .maps.tilesources import kartverket as kartverket_tiles
|
|
108
98
|
from .maps.tilesources import xyz as xyztiles
|
|
109
|
-
from .networkanalysis.closing_network_holes import
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
from .networkanalysis.cutting_lines import
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
from .networkanalysis.directednetwork import (
|
|
119
|
-
make_directed_network,
|
|
120
|
-
make_directed_network_norway,
|
|
121
|
-
)
|
|
122
|
-
from .networkanalysis.finding_isolated_networks import (
|
|
123
|
-
get_component_size,
|
|
124
|
-
get_connected_components,
|
|
125
|
-
)
|
|
99
|
+
from .networkanalysis.closing_network_holes import close_network_holes
|
|
100
|
+
from .networkanalysis.closing_network_holes import close_network_holes_to_deadends
|
|
101
|
+
from .networkanalysis.cutting_lines import cut_lines
|
|
102
|
+
from .networkanalysis.cutting_lines import cut_lines_once
|
|
103
|
+
from .networkanalysis.cutting_lines import split_lines_by_nearest_point
|
|
104
|
+
from .networkanalysis.directednetwork import make_directed_network
|
|
105
|
+
from .networkanalysis.directednetwork import make_directed_network_norway
|
|
106
|
+
from .networkanalysis.finding_isolated_networks import get_component_size
|
|
107
|
+
from .networkanalysis.finding_isolated_networks import get_connected_components
|
|
126
108
|
from .networkanalysis.network import Network
|
|
127
109
|
from .networkanalysis.networkanalysis import NetworkAnalysis
|
|
128
110
|
from .networkanalysis.networkanalysisrules import NetworkAnalysisRules
|
|
129
|
-
from .networkanalysis.nodes import
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
make_node_ids,
|
|
133
|
-
)
|
|
111
|
+
from .networkanalysis.nodes import make_edge_coords_cols
|
|
112
|
+
from .networkanalysis.nodes import make_edge_wkt_cols
|
|
113
|
+
from .networkanalysis.nodes import make_node_ids
|
|
134
114
|
from .networkanalysis.traveling_salesman import traveling_salesman_problem
|
|
135
|
-
from .parallel.parallel import Parallel
|
|
115
|
+
from .parallel.parallel import Parallel
|
|
116
|
+
from .parallel.parallel import parallel_overlay
|
|
136
117
|
from .raster.cube import DataCube
|
|
137
118
|
|
|
138
|
-
|
|
139
119
|
try:
|
|
140
120
|
import sgis.raster.torchgeo as torchgeo
|
|
141
121
|
except ImportError:
|
|
@@ -143,6 +123,8 @@ except ImportError:
|
|
|
143
123
|
|
|
144
124
|
|
|
145
125
|
try:
|
|
146
|
-
from .io.dapla_functions import check_files
|
|
126
|
+
from .io.dapla_functions import check_files
|
|
127
|
+
from .io.dapla_functions import read_geopandas
|
|
128
|
+
from .io.dapla_functions import write_geopandas
|
|
147
129
|
except ImportError:
|
|
148
130
|
pass
|
sgis/exceptions.py
CHANGED
|
@@ -7,10 +7,12 @@ class NoPointsWithinSearchToleranceError(Exception):
|
|
|
7
7
|
def __init__(
|
|
8
8
|
self, what: str | None = None, search_tolerance: str | None = None
|
|
9
9
|
) -> None:
|
|
10
|
+
"""Initialise error class."""
|
|
10
11
|
self.what = what
|
|
11
12
|
self.search_tolerance = search_tolerance
|
|
12
13
|
|
|
13
|
-
def __str__(self):
|
|
14
|
+
def __str__(self) -> str:
|
|
15
|
+
"""String representation."""
|
|
14
16
|
return (
|
|
15
17
|
f"No {self.what} within specified 'search_tolerance' "
|
|
16
18
|
f"of {self.search_tolerance}"
|
sgis/geopandas_tools/__init__.py
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Tools for vector gis."""
|
sgis/geopandas_tools/bounds.py
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import functools
|
|
2
|
-
import
|
|
3
|
-
from collections.abc import Callable, Collection, Mapping
|
|
2
|
+
from collections.abc import Callable
|
|
4
3
|
from dataclasses import dataclass
|
|
5
4
|
from typing import Any
|
|
6
5
|
|
|
7
6
|
import geopandas as gpd
|
|
8
7
|
import numpy as np
|
|
9
8
|
import pandas as pd
|
|
10
|
-
from geopandas import GeoDataFrame
|
|
11
|
-
from
|
|
12
|
-
from
|
|
9
|
+
from geopandas import GeoDataFrame
|
|
10
|
+
from geopandas import GeoSeries
|
|
11
|
+
from pyproj import CRS
|
|
12
|
+
from shapely import Geometry
|
|
13
|
+
from shapely import box
|
|
14
|
+
from shapely import extract_unique_points
|
|
13
15
|
from shapely.geometry import Polygon
|
|
14
16
|
|
|
15
17
|
from ..parallel.parallel import Parallel
|
|
16
|
-
from .conversion import to_bbox
|
|
17
|
-
from .
|
|
18
|
+
from .conversion import to_bbox
|
|
19
|
+
from .conversion import to_gdf
|
|
20
|
+
from .general import clean_clip
|
|
21
|
+
from .general import is_bbox_like
|
|
18
22
|
|
|
19
23
|
|
|
20
24
|
@dataclass
|
|
@@ -32,9 +36,8 @@ class Gridlooper:
|
|
|
32
36
|
keep_geom_type: Whether to keep only the input geometry types after clipping.
|
|
33
37
|
Defaults to True.
|
|
34
38
|
|
|
35
|
-
Examples
|
|
39
|
+
Examples:
|
|
36
40
|
--------
|
|
37
|
-
|
|
38
41
|
Get some points and some polygons.
|
|
39
42
|
|
|
40
43
|
>>> import sgis as sg
|
|
@@ -46,7 +49,7 @@ class Gridlooper:
|
|
|
46
49
|
0 0 POLYGON ((263222.700 6651184.900, 263222.651 6...
|
|
47
50
|
1 1 POLYGON ((272556.100 6653369.500, 272556.051 6...
|
|
48
51
|
2 2 POLYGON ((270182.300 6653032.700, 270182.251 6...
|
|
49
|
-
|
|
52
|
+
3 3 POLYGON ((259904.800 6650339.700, 259904.751 6...
|
|
50
53
|
4 4 POLYGON ((272976.200 6652889.100, 272976.151 6...
|
|
51
54
|
.. ... ...
|
|
52
55
|
995 995 POLYGON ((266901.700 6647844.500, 266901.651 6...
|
|
@@ -95,16 +98,24 @@ class Gridlooper:
|
|
|
95
98
|
keep_geom_type: bool = True
|
|
96
99
|
verbose: bool = False
|
|
97
100
|
|
|
98
|
-
def __post_init__(self):
|
|
101
|
+
def __post_init__(self) -> None:
|
|
102
|
+
"""Fix types."""
|
|
99
103
|
if not isinstance(self.mask, GeoDataFrame):
|
|
100
104
|
self.mask = to_gdf(self.mask)
|
|
101
105
|
|
|
102
|
-
def run(self, func: Callable, *args, **kwargs):
|
|
103
|
-
|
|
106
|
+
def run(self, func: Callable, *args, **kwargs) -> Any | list[Any]:
|
|
107
|
+
"""Run a function for each grid cell in a loop.
|
|
108
|
+
|
|
109
|
+
Returns a list of the return values from the function,
|
|
110
|
+
or a (Geo)DataFrame if self.concat is True.
|
|
111
|
+
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
def _intersects_mask(df: GeoDataFrame) -> pd.Series:
|
|
104
115
|
return df.index.isin(df.sjoin(self.mask).index)
|
|
105
116
|
|
|
106
117
|
grid: GeoSeries = (
|
|
107
|
-
make_grid(self.mask, gridsize=self.gridsize).loc[
|
|
118
|
+
make_grid(self.mask, gridsize=self.gridsize).loc[_intersects_mask].geometry
|
|
108
119
|
)
|
|
109
120
|
|
|
110
121
|
n = len(grid)
|
|
@@ -137,7 +148,9 @@ class Gridlooper:
|
|
|
137
148
|
return out if not self.concat else pd.concat(out, ignore_index=True)
|
|
138
149
|
|
|
139
150
|
results = []
|
|
140
|
-
for i, (unbuffered, buffered) in enumerate(
|
|
151
|
+
for i, (unbuffered, buffered) in enumerate(
|
|
152
|
+
zip(grid, buffered_grid, strict=False)
|
|
153
|
+
):
|
|
141
154
|
cell_kwargs = {
|
|
142
155
|
key: _clip_if_isinstance(
|
|
143
156
|
value, buffered, self.keep_geom_type, self.clip
|
|
@@ -200,13 +213,16 @@ def gridloop(
|
|
|
200
213
|
kwargs: Keyword arguments to pass to the function. Arguments
|
|
201
214
|
of type GeoDataFrame or GeoSeries will be clipped by the grid cells in
|
|
202
215
|
a loop.
|
|
216
|
+
parallelizer: Optional instance of sgis.Parallel, to run the function in parallel.
|
|
203
217
|
|
|
204
218
|
Returns:
|
|
205
219
|
List of results with the same length as number of grid cells.
|
|
206
220
|
|
|
207
|
-
|
|
208
|
-
|
|
221
|
+
Raises:
|
|
222
|
+
TypeError: If args or kwargs has a wrong type
|
|
209
223
|
|
|
224
|
+
Examples:
|
|
225
|
+
--------
|
|
210
226
|
Get some points and some polygons.
|
|
211
227
|
|
|
212
228
|
>>> import sgis as sg
|
|
@@ -274,8 +290,10 @@ def gridloop(
|
|
|
274
290
|
if not isinstance(mask, GeoDataFrame):
|
|
275
291
|
mask = to_gdf(mask)
|
|
276
292
|
|
|
277
|
-
|
|
278
|
-
|
|
293
|
+
def _intersects_mask(df: GeoDataFrame) -> pd.Series:
|
|
294
|
+
return df.index.isin(df.sjoin(mask).index)
|
|
295
|
+
|
|
296
|
+
grid: GeoSeries = make_grid(mask, gridsize=gridsize).loc[_intersects_mask].geometry
|
|
279
297
|
|
|
280
298
|
n = len(grid)
|
|
281
299
|
|
|
@@ -301,7 +319,7 @@ def gridloop(
|
|
|
301
319
|
return out
|
|
302
320
|
|
|
303
321
|
results = []
|
|
304
|
-
for i, (unbuffered, buffered) in enumerate(zip(grid, buffered_grid)):
|
|
322
|
+
for i, (unbuffered, buffered) in enumerate(zip(grid, buffered_grid, strict=False)):
|
|
305
323
|
cell_kwargs = {
|
|
306
324
|
key: _clip_if_isinstance(value, buffered, keep_geom_type, clip)
|
|
307
325
|
for key, value in kwargs.items()
|
|
@@ -333,7 +351,7 @@ def _clip_and_run_func(
|
|
|
333
351
|
kwargs: dict,
|
|
334
352
|
keep_geom_type: bool,
|
|
335
353
|
clip: bool,
|
|
336
|
-
):
|
|
354
|
+
) -> Any:
|
|
337
355
|
cell_args = tuple(
|
|
338
356
|
_clip_if_isinstance(value, grid_cell, keep_geom_type, clip) for value in args
|
|
339
357
|
)
|
|
@@ -345,11 +363,13 @@ def _clip_and_run_func(
|
|
|
345
363
|
return func(*cell_args, **cell_kwargs)
|
|
346
364
|
|
|
347
365
|
|
|
348
|
-
def _clip_if_isinstance(
|
|
349
|
-
|
|
366
|
+
def _clip_if_isinstance(
|
|
367
|
+
value: Any, cell: Geometry, keep_geom_type: bool, clip: bool
|
|
368
|
+
) -> Any:
|
|
369
|
+
if not isinstance(value, (gpd.GeoDataFrame | gpd.GeoSeries | Geometry)):
|
|
350
370
|
return value
|
|
351
371
|
|
|
352
|
-
if isinstance(value, (gpd.GeoDataFrame
|
|
372
|
+
if isinstance(value, (gpd.GeoDataFrame | gpd.GeoSeries)):
|
|
353
373
|
if clip:
|
|
354
374
|
return clean_clip(value, cell, keep_geom_type=keep_geom_type)
|
|
355
375
|
return value.loc[value.intersects(cell)]
|
|
@@ -357,10 +377,12 @@ def _clip_if_isinstance(value, cell, keep_geom_type, clip: bool):
|
|
|
357
377
|
return value.intersection(cell).make_valid()
|
|
358
378
|
|
|
359
379
|
|
|
360
|
-
def _clip_back_to_unbuffered_grid(
|
|
361
|
-
|
|
380
|
+
def _clip_back_to_unbuffered_grid(
|
|
381
|
+
results: Any, mask: GeoDataFrame, keep_geom_type: bool
|
|
382
|
+
) -> Any:
|
|
383
|
+
if isinstance(results, (gpd.GeoDataFrame | gpd.GeoSeries | Geometry)):
|
|
362
384
|
return _clip_if_isinstance(results, mask, keep_geom_type, clip=True)
|
|
363
|
-
elif isinstance(results, (pd.DataFrame
|
|
385
|
+
elif isinstance(results, (pd.DataFrame | pd.Series | np.ndarray)):
|
|
364
386
|
return results
|
|
365
387
|
try:
|
|
366
388
|
for key, value in results.items():
|
|
@@ -383,7 +405,7 @@ def make_grid_from_bbox(
|
|
|
383
405
|
maxy: int | float,
|
|
384
406
|
*_,
|
|
385
407
|
gridsize: int | float,
|
|
386
|
-
crs,
|
|
408
|
+
crs: CRS | int | str,
|
|
387
409
|
) -> GeoDataFrame:
|
|
388
410
|
"""Creates a polygon grid from a bounding box.
|
|
389
411
|
|
|
@@ -420,7 +442,7 @@ def make_grid(
|
|
|
420
442
|
obj: GeoDataFrame | GeoSeries | Geometry | tuple,
|
|
421
443
|
gridsize: int | float,
|
|
422
444
|
*,
|
|
423
|
-
crs=None,
|
|
445
|
+
crs: CRS = None,
|
|
424
446
|
clip_to_bounds: bool = False,
|
|
425
447
|
) -> GeoDataFrame:
|
|
426
448
|
"""Create a polygon grid around geometries.
|
|
@@ -439,8 +461,11 @@ def make_grid(
|
|
|
439
461
|
Returns:
|
|
440
462
|
GeoDataFrame with grid polygons.
|
|
441
463
|
|
|
464
|
+
Raises:
|
|
465
|
+
ValueError: crs can only be None if obj is GeoDataFrame/GeoSeries.
|
|
466
|
+
|
|
442
467
|
"""
|
|
443
|
-
if isinstance(obj, (GeoDataFrame
|
|
468
|
+
if isinstance(obj, (GeoDataFrame | GeoSeries)):
|
|
444
469
|
crs = obj.crs or crs
|
|
445
470
|
elif not crs:
|
|
446
471
|
raise ValueError(
|
|
@@ -475,14 +500,17 @@ def make_ssb_grid(
|
|
|
475
500
|
Args:
|
|
476
501
|
gdf: A GeoDataFrame.
|
|
477
502
|
gridsize: Size of the grid in meters.
|
|
503
|
+
add: Number of grid cells to add on each side,
|
|
504
|
+
to make sure all data is covered by the grid.
|
|
478
505
|
|
|
479
506
|
Returns:
|
|
480
507
|
GeoDataFrame with grid geometries and a column 'SSBID'.
|
|
481
508
|
|
|
482
509
|
Raises:
|
|
483
510
|
ValueError: If the GeoDataFrame does not have 25833 as crs.
|
|
511
|
+
TypeError: if gdf has wrong type.
|
|
484
512
|
"""
|
|
485
|
-
if not isinstance(gdf, (GeoDataFrame
|
|
513
|
+
if not isinstance(gdf, (GeoDataFrame | GeoSeries)):
|
|
486
514
|
raise TypeError("gdf must be GeoDataFrame og GeoSeries.")
|
|
487
515
|
|
|
488
516
|
if not gdf.crs.equals(25833):
|
|
@@ -551,6 +579,7 @@ def add_grid_id(
|
|
|
551
579
|
Args:
|
|
552
580
|
gdf: A GeoDataFrame.
|
|
553
581
|
gridsize: Size of the grid in meters.
|
|
582
|
+
out_column: Name of column for the grid id.
|
|
554
583
|
|
|
555
584
|
Returns:
|
|
556
585
|
The input GeoDataFrame with a new grid id column.
|
|
@@ -587,9 +616,9 @@ def bounds_to_polygon(
|
|
|
587
616
|
Returns:
|
|
588
617
|
GeoDataFrame of box polygons with length and index of 'gdf'.
|
|
589
618
|
|
|
590
|
-
Examples
|
|
619
|
+
Examples:
|
|
591
620
|
--------
|
|
592
|
-
|
|
621
|
+
>>> import sgis as sg
|
|
593
622
|
>>> gdf = sg.to_gdf([MultiPoint([(0, 0), (1, 1)]), Point(0, 0)])
|
|
594
623
|
>>> gdf
|
|
595
624
|
geometry
|
|
@@ -622,8 +651,9 @@ def bounds_to_points(
|
|
|
622
651
|
Returns:
|
|
623
652
|
GeoDataFrame of multipoints with same length and index as 'gdf'.
|
|
624
653
|
|
|
625
|
-
Examples
|
|
654
|
+
Examples:
|
|
626
655
|
--------
|
|
656
|
+
>>> import sgis as sg
|
|
627
657
|
>>> gdf = sg.to_gdf([MultiPoint([(0, 0), (1, 1)]), Point(0, 0)])
|
|
628
658
|
>>> gdf
|
|
629
659
|
geometry
|
|
@@ -643,19 +673,26 @@ def bounds_to_points(
|
|
|
643
673
|
|
|
644
674
|
|
|
645
675
|
def get_total_bounds(
|
|
646
|
-
*geometries: GeoDataFrame | GeoSeries | Geometry,
|
|
676
|
+
*geometries: GeoDataFrame | GeoSeries | Geometry, strict: bool = False
|
|
647
677
|
) -> tuple[float, float, float, float]:
|
|
648
678
|
"""Get a combined total bounds of multiple geometry objects."""
|
|
649
679
|
xs, ys = [], []
|
|
650
680
|
for obj in geometries:
|
|
651
|
-
|
|
681
|
+
try:
|
|
682
|
+
minx, miny, maxx, maxy = to_bbox(obj)
|
|
683
|
+
except Exception as e:
|
|
684
|
+
if strict:
|
|
685
|
+
raise e
|
|
686
|
+
else:
|
|
687
|
+
continue
|
|
652
688
|
xs += [minx, maxx]
|
|
653
689
|
ys += [miny, maxy]
|
|
654
690
|
return min(xs), min(ys), max(xs), max(ys)
|
|
655
691
|
|
|
656
692
|
|
|
657
|
-
def points_in_bounds(gdf: GeoDataFrame | GeoSeries, n2: int):
|
|
658
|
-
|
|
693
|
+
def points_in_bounds(gdf: GeoDataFrame | GeoSeries, n2: int) -> GeoDataFrame:
|
|
694
|
+
"""Get a GeoDataFrame of points within the bounds of the GeoDataFrame."""
|
|
695
|
+
if not isinstance(gdf, (GeoDataFrame | GeoSeries)) and is_bbox_like(gdf):
|
|
659
696
|
minx, miny, maxx, maxy = gdf
|
|
660
697
|
else:
|
|
661
698
|
minx, miny, maxx, maxy = gdf.total_bounds
|