ssb-sgis 1.0.1__py3-none-any.whl → 1.0.3__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 +107 -121
- sgis/exceptions.py +5 -3
- sgis/geopandas_tools/__init__.py +1 -0
- sgis/geopandas_tools/bounds.py +86 -47
- sgis/geopandas_tools/buffer_dissolve_explode.py +62 -39
- sgis/geopandas_tools/centerlines.py +53 -44
- sgis/geopandas_tools/cleaning.py +87 -104
- sgis/geopandas_tools/conversion.py +164 -107
- sgis/geopandas_tools/duplicates.py +33 -19
- sgis/geopandas_tools/general.py +84 -52
- sgis/geopandas_tools/geometry_types.py +24 -10
- sgis/geopandas_tools/neighbors.py +23 -11
- sgis/geopandas_tools/overlay.py +136 -53
- sgis/geopandas_tools/point_operations.py +11 -10
- sgis/geopandas_tools/polygon_operations.py +53 -61
- sgis/geopandas_tools/polygons_as_rings.py +121 -78
- sgis/geopandas_tools/sfilter.py +17 -17
- sgis/helpers.py +116 -58
- sgis/io/dapla_functions.py +32 -23
- sgis/io/opener.py +13 -6
- sgis/io/read_parquet.py +2 -2
- sgis/maps/examine.py +55 -28
- sgis/maps/explore.py +471 -112
- sgis/maps/httpserver.py +12 -12
- sgis/maps/legend.py +285 -134
- sgis/maps/map.py +248 -129
- sgis/maps/maps.py +123 -119
- sgis/maps/thematicmap.py +260 -94
- 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 +22 -64
- sgis/networkanalysis/cutting_lines.py +58 -46
- sgis/networkanalysis/directednetwork.py +16 -8
- sgis/networkanalysis/finding_isolated_networks.py +6 -5
- sgis/networkanalysis/network.py +15 -13
- sgis/networkanalysis/networkanalysis.py +79 -61
- sgis/networkanalysis/networkanalysisrules.py +21 -17
- sgis/networkanalysis/nodes.py +2 -3
- sgis/networkanalysis/traveling_salesman.py +6 -3
- sgis/parallel/parallel.py +372 -142
- sgis/raster/base.py +9 -3
- sgis/raster/cube.py +331 -213
- sgis/raster/cubebase.py +15 -29
- sgis/raster/image_collection.py +2560 -0
- sgis/raster/indices.py +17 -12
- sgis/raster/raster.py +356 -275
- sgis/raster/sentinel_config.py +104 -0
- sgis/raster/zonal.py +38 -14
- {ssb_sgis-1.0.1.dist-info → ssb_sgis-1.0.3.dist-info}/LICENSE +1 -1
- {ssb_sgis-1.0.1.dist-info → ssb_sgis-1.0.3.dist-info}/METADATA +87 -16
- ssb_sgis-1.0.3.dist-info/RECORD +61 -0
- {ssb_sgis-1.0.1.dist-info → ssb_sgis-1.0.3.dist-info}/WHEEL +1 -1
- sgis/raster/bands.py +0 -48
- sgis/raster/gradient.py +0 -78
- sgis/raster/methods_as_functions.py +0 -124
- sgis/raster/torchgeo.py +0 -150
- ssb_sgis-1.0.1.dist-info/RECORD +0 -63
sgis/__init__.py
CHANGED
|
@@ -2,147 +2,133 @@ 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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
118
|
+
from .raster.cube import concat_cubes
|
|
119
|
+
from .raster.image_collection import Band
|
|
120
|
+
from .raster.image_collection import Image
|
|
121
|
+
from .raster.image_collection import ImageCollection
|
|
122
|
+
from .raster.image_collection import Sentinel2Band
|
|
123
|
+
from .raster.image_collection import Sentinel2CloudlessCollection
|
|
124
|
+
from .raster.image_collection import Sentinel2CloudlessImage
|
|
125
|
+
from .raster.image_collection import Sentinel2Collection
|
|
126
|
+
from .raster.image_collection import Sentinel2Image
|
|
127
|
+
from .raster.image_collection import concat_image_collections
|
|
144
128
|
|
|
145
129
|
try:
|
|
146
|
-
from .io.dapla_functions import check_files
|
|
130
|
+
from .io.dapla_functions import check_files
|
|
131
|
+
from .io.dapla_functions import read_geopandas
|
|
132
|
+
from .io.dapla_functions import write_geopandas
|
|
147
133
|
except ImportError:
|
|
148
134
|
pass
|
sgis/exceptions.py
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
"""Some small exception classes."""
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class NoPointsWithinSearchToleranceError(
|
|
4
|
+
class NoPointsWithinSearchToleranceError(ValueError):
|
|
5
5
|
"""Exception for when the points are too far away from the network."""
|
|
6
6
|
|
|
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}"
|
|
17
19
|
)
|
|
18
20
|
|
|
19
21
|
|
|
20
|
-
class ZeroLinesError(
|
|
22
|
+
class ZeroLinesError(ValueError):
|
|
21
23
|
"""DataFrame has 0 rows."""
|
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
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
Examples:
|
|
40
|
+
---------
|
|
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 = None,
|
|
424
446
|
clip_to_bounds: bool = False,
|
|
425
447
|
) -> GeoDataFrame:
|
|
426
448
|
"""Create a polygon grid around geometries.
|
|
@@ -439,13 +461,12 @@ 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
|
-
elif not crs:
|
|
446
|
-
raise ValueError(
|
|
447
|
-
"'crs' cannot be None when 'obj' is not GeoDataFrame/GeoSeries."
|
|
448
|
-
)
|
|
449
470
|
if hasattr(obj, "__len__") and not len(obj):
|
|
450
471
|
return GeoDataFrame({"geometry": []}, crs=crs)
|
|
451
472
|
|
|
@@ -475,14 +496,17 @@ def make_ssb_grid(
|
|
|
475
496
|
Args:
|
|
476
497
|
gdf: A GeoDataFrame.
|
|
477
498
|
gridsize: Size of the grid in meters.
|
|
499
|
+
add: Number of grid cells to add on each side,
|
|
500
|
+
to make sure all data is covered by the grid.
|
|
478
501
|
|
|
479
502
|
Returns:
|
|
480
503
|
GeoDataFrame with grid geometries and a column 'SSBID'.
|
|
481
504
|
|
|
482
505
|
Raises:
|
|
483
506
|
ValueError: If the GeoDataFrame does not have 25833 as crs.
|
|
507
|
+
TypeError: if gdf has wrong type.
|
|
484
508
|
"""
|
|
485
|
-
if not isinstance(gdf, (GeoDataFrame
|
|
509
|
+
if not isinstance(gdf, (GeoDataFrame | GeoSeries)):
|
|
486
510
|
raise TypeError("gdf must be GeoDataFrame og GeoSeries.")
|
|
487
511
|
|
|
488
512
|
if not gdf.crs.equals(25833):
|
|
@@ -551,6 +575,7 @@ def add_grid_id(
|
|
|
551
575
|
Args:
|
|
552
576
|
gdf: A GeoDataFrame.
|
|
553
577
|
gridsize: Size of the grid in meters.
|
|
578
|
+
out_column: Name of column for the grid id.
|
|
554
579
|
|
|
555
580
|
Returns:
|
|
556
581
|
The input GeoDataFrame with a new grid id column.
|
|
@@ -587,9 +612,9 @@ def bounds_to_polygon(
|
|
|
587
612
|
Returns:
|
|
588
613
|
GeoDataFrame of box polygons with length and index of 'gdf'.
|
|
589
614
|
|
|
590
|
-
Examples
|
|
591
|
-
|
|
592
|
-
|
|
615
|
+
Examples:
|
|
616
|
+
---------
|
|
617
|
+
>>> import sgis as sg
|
|
593
618
|
>>> gdf = sg.to_gdf([MultiPoint([(0, 0), (1, 1)]), Point(0, 0)])
|
|
594
619
|
>>> gdf
|
|
595
620
|
geometry
|
|
@@ -622,8 +647,9 @@ def bounds_to_points(
|
|
|
622
647
|
Returns:
|
|
623
648
|
GeoDataFrame of multipoints with same length and index as 'gdf'.
|
|
624
649
|
|
|
625
|
-
Examples
|
|
626
|
-
|
|
650
|
+
Examples:
|
|
651
|
+
---------
|
|
652
|
+
>>> import sgis as sg
|
|
627
653
|
>>> gdf = sg.to_gdf([MultiPoint([(0, 0), (1, 1)]), Point(0, 0)])
|
|
628
654
|
>>> gdf
|
|
629
655
|
geometry
|
|
@@ -643,19 +669,32 @@ def bounds_to_points(
|
|
|
643
669
|
|
|
644
670
|
|
|
645
671
|
def get_total_bounds(
|
|
646
|
-
*geometries: GeoDataFrame | GeoSeries | Geometry,
|
|
672
|
+
*geometries: GeoDataFrame | GeoSeries | Geometry, strict: bool = False
|
|
647
673
|
) -> tuple[float, float, float, float]:
|
|
648
674
|
"""Get a combined total bounds of multiple geometry objects."""
|
|
649
675
|
xs, ys = [], []
|
|
650
676
|
for obj in geometries:
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
677
|
+
try:
|
|
678
|
+
minx, miny, maxx, maxy = to_bbox(obj)
|
|
679
|
+
xs += [minx, maxx]
|
|
680
|
+
ys += [miny, maxy]
|
|
681
|
+
except Exception as e:
|
|
682
|
+
try:
|
|
683
|
+
for x in obj:
|
|
684
|
+
minx, miny, maxx, maxy = to_bbox(x)
|
|
685
|
+
xs += [minx, maxx]
|
|
686
|
+
ys += [miny, maxy]
|
|
687
|
+
except Exception as e2:
|
|
688
|
+
if strict:
|
|
689
|
+
raise e2 from e
|
|
690
|
+
else:
|
|
691
|
+
continue
|
|
654
692
|
return min(xs), min(ys), max(xs), max(ys)
|
|
655
693
|
|
|
656
694
|
|
|
657
|
-
def points_in_bounds(gdf: GeoDataFrame | GeoSeries, n2: int):
|
|
658
|
-
|
|
695
|
+
def points_in_bounds(gdf: GeoDataFrame | GeoSeries, n2: int) -> GeoDataFrame:
|
|
696
|
+
"""Get a GeoDataFrame of points within the bounds of the GeoDataFrame."""
|
|
697
|
+
if not isinstance(gdf, (GeoDataFrame | GeoSeries)) and is_bbox_like(gdf):
|
|
659
698
|
minx, miny, maxx, maxy = gdf
|
|
660
699
|
else:
|
|
661
700
|
minx, miny, maxx, maxy = gdf.total_bounds
|