ssb-sgis 1.2.6__py3-none-any.whl → 1.2.8__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/maps/wms.py CHANGED
@@ -4,18 +4,33 @@ import json
4
4
  import re
5
5
  from collections.abc import Iterable
6
6
  from dataclasses import dataclass
7
+ from io import BytesIO
7
8
  from pathlib import Path
8
9
  from typing import Any
9
10
  from urllib.request import urlopen
10
11
 
11
12
  import folium
13
+ import numpy as np
14
+ import pandas as pd
12
15
  import shapely
13
-
16
+ from geopandas import GeoDataFrame
17
+ from geopandas import GeoSeries
18
+ from shapely import Geometry
19
+ from shapely import get_exterior_ring
20
+ from shapely import make_valid
21
+ from shapely import polygons
22
+ from shapely import set_precision
23
+ from shapely import simplify
24
+ from shapely.errors import GEOSException
25
+
26
+ from ..geopandas_tools.conversion import to_gdf
14
27
  from ..geopandas_tools.conversion import to_shapely
28
+ from ..geopandas_tools.sfilter import sfilter
29
+ from ..raster.image_collection import Band
15
30
 
16
31
  JSON_PATH = Path(__file__).parent / "norge_i_bilder.json"
17
32
 
18
- JSON_YEARS = [str(year) for year in range(1999, 2025)]
33
+ JSON_YEARS = [str(year) for year in range(2006, datetime.datetime.now().year + 1)]
19
34
 
20
35
  DEFAULT_YEARS: tuple[str] = tuple(
21
36
  str(year)
@@ -57,7 +72,7 @@ class NorgeIBilderWms(WmsLoader):
57
72
  show: bool | Iterable[int] | int = False
58
73
  _use_json: bool = True
59
74
 
60
- def load_tiles(self) -> None:
75
+ def load_tiles(self, verbose: bool = False) -> None:
61
76
  """Load all Norge i bilder tiles into self.tiles."""
62
77
  url = "https://wms.geonorge.no/skwms1/wms.nib-prosjekter?SERVICE=WMS&REQUEST=GetCapabilities"
63
78
 
@@ -107,7 +122,10 @@ class NorgeIBilderWms(WmsLoader):
107
122
  this_tile["name"] = name
108
123
  this_tile["bbox"] = this_bbox
109
124
  year = name.split(" ")[-1]
110
- if year.isnumeric() and len(year) == 4:
125
+ is_year_or_interval: bool = all(
126
+ part.isnumeric() and len(part) == 4 for part in year.split("-")
127
+ )
128
+ if is_year_or_interval:
111
129
  this_tile["year"] = year
112
130
  else:
113
131
  this_tile["year"] = "9999"
@@ -116,41 +134,123 @@ class NorgeIBilderWms(WmsLoader):
116
134
 
117
135
  self.tiles = sorted(all_tiles, key=lambda x: x["year"])
118
136
 
119
- def get_tiles(self, bbox: Any, max_zoom: int = 40) -> list[folium.WmsTileLayer]:
120
- """Get all Norge i bilder tiles intersecting with a bbox."""
137
+ masks = self._get_norge_i_bilder_polygon_masks(verbose=verbose)
138
+ for tile in self.tiles:
139
+ mask = masks.get(tile["name"], None)
140
+ tile["geometry"] = mask
141
+
142
+ def _get_norge_i_bilder_polygon_masks(self, verbose: bool):
143
+ from owslib.util import ServiceException
144
+ from owslib.wms import WebMapService
145
+ from PIL import Image
146
+
147
+ relevant_names: dict[str, str] = {x["name"]: x["bbox"] for x in self.tiles}
148
+ assert len(relevant_names), relevant_names
149
+
150
+ url = "https://wms.geonorge.no/skwms1/wms.nib-mosaikk?SERVICE=WMS&REQUEST=GetCapabilities"
151
+ wms = WebMapService(url, version="1.3.0")
152
+ out = {}
153
+ # ttiles = {wms[layer].title: [] for layer in list(wms.contents)}
154
+ # for layer in list(wms.contents):
155
+ # if wms[layer].title not in relevant_names:
156
+ # continue
157
+ # ttiles[wms[layer].title].append(layer)
158
+ # import pandas as pd
159
+
160
+ # df = pd.Series(ttiles).to_frame("title")
161
+ # df["n"] = df["title"].str.len()
162
+ # df = df.sort_values("n")
163
+ # for x in df["title"]:
164
+ # if len(x) == 1:
165
+ # continue
166
+ # bounds = {tuple(wms[layer].boundingBoxWGS84) for layer in x}
167
+ # if len(bounds) <= 1:
168
+ # continue
169
+ # print()
170
+ # for layer in x:
171
+ # print(layer)
172
+ # print(wms[layer].title)
173
+ # bbox = wms[layer].boundingBoxWGS84
174
+ # print(bbox)
175
+
176
+ for layer in list(wms.contents):
177
+ title = wms[layer].title
178
+ if title not in relevant_names:
179
+ continue
180
+ bbox = wms[layer].boundingBoxWGS84
181
+ bbox = tuple(to_gdf(bbox, crs=4326).to_crs(25832).total_bounds)
182
+
183
+ existing_bbox = relevant_names[title]
184
+ existing_bbox = to_gdf(existing_bbox, crs=4326).to_crs(25832).union_all()
185
+ if not to_shapely(bbox).intersects(existing_bbox):
186
+ continue
187
+ diffx = bbox[2] - bbox[0]
188
+ diffy = bbox[3] - bbox[1]
189
+ width = int(diffx / 40)
190
+ height = int(diffy / 40)
191
+ if not bbox:
192
+ continue
193
+ try:
194
+ img = wms.getmap(
195
+ layers=[layer],
196
+ styles=[""], # Empty unless you know the style
197
+ srs="EPSG:25832",
198
+ bbox=bbox,
199
+ size=(width, height),
200
+ format="image/jpeg",
201
+ transparent=True,
202
+ bgcolor="#FFFFFF",
203
+ )
204
+ except (ServiceException, AttributeError) as e:
205
+ if verbose:
206
+ print(type(e), e)
207
+ continue
208
+
209
+ arr = np.array(Image.open(BytesIO(img.read())))
210
+ if not np.sum(arr):
211
+ continue
212
+
213
+ band = Band(
214
+ np.where(np.any(arr != 0, axis=-1), 1, 0), bounds=bbox, crs=25832
215
+ )
216
+ polygon = band.to_geopandas()[lambda x: x["value"] == 1].geometry.values
217
+ polygon = make_valid(polygons(get_exterior_ring(polygon)))
218
+ polygon = make_valid(set_precision(polygon, 1))
219
+ polygon = make_valid(simplify(polygon, 100))
220
+ polygon = make_valid(set_precision(polygon, 1))
221
+ polygon = GeoSeries(polygon, crs=25832).to_crs(4326)
222
+ if verbose:
223
+ print(f"Layer name: {layer}")
224
+ print(f"Title: {wms[layer].title}")
225
+ print(f"Bounding box: {wms[layer].boundingBoxWGS84}")
226
+ print(f"polygon: {polygon}")
227
+ print("-" * 40)
228
+
229
+ for x in [0, 0.1, 0.001, 1]:
230
+ try:
231
+ out[title] = make_valid(polygon.buffer(x).make_valid().union_all())
232
+ except GEOSException:
233
+ pass
234
+ break
235
+
236
+ return out
237
+
238
+ def get_tiles(self, mask: Any, max_zoom: int = 40) -> list[folium.WmsTileLayer]:
239
+ """Get all Norge i bilder tiles intersecting with a mask (bbox or polygon)."""
121
240
  if self.tiles is None:
122
241
  self.load_tiles()
123
242
 
124
- all_tiles = {}
125
-
126
- bbox = to_shapely(bbox)
243
+ if not isinstance(mask, (GeoSeries | GeoDataFrame | Geometry)):
244
+ mask = to_shapely(mask)
127
245
 
128
246
  if isinstance(self.show, bool):
129
247
  show = self.show
130
248
  else:
131
249
  show = False
132
250
 
133
- for tile in self.tiles:
134
- if not tile["bbox"] or not tile["bbox"].intersects(bbox):
135
- continue
136
-
137
- name = tile["name"]
138
-
139
- if (
140
- not name
141
- or not any(year in name for year in self.years)
142
- or (
143
- self.contains
144
- and not any(re.search(x, name.lower()) for x in self.contains)
145
- )
146
- or (
147
- self.not_contains
148
- and any(re.search(x, name.lower()) for x in self.not_contains)
149
- )
150
- ):
151
- continue
152
-
153
- all_tiles[name] = folium.WmsTileLayer(
251
+ relevant_tiles = self._filter_tiles(mask)
252
+ tile_layers = {
253
+ name: folium.WmsTileLayer(
154
254
  url="https://wms.geonorge.no/skwms1/wms.nib-prosjekter",
155
255
  name=name,
156
256
  layers=name,
@@ -161,16 +261,37 @@ class NorgeIBilderWms(WmsLoader):
161
261
  show=show,
162
262
  max_zoom=max_zoom,
163
263
  )
264
+ for name in relevant_tiles["name"]
265
+ }
266
+
267
+ if not len(tile_layers):
268
+ return tile_layers
164
269
 
165
270
  if isinstance(self.show, int):
166
- tile = all_tiles[list(all_tiles)[self.show]]
271
+ tile = tile_layers[list(tile_layers)[self.show]]
167
272
  tile.show = True
168
273
  elif isinstance(self.show, Iterable):
169
274
  for i in self.show:
170
- tile = all_tiles[list(all_tiles)[i]]
275
+ tile = tile_layers[list(tile_layers)[i]]
171
276
  tile.show = True
172
277
 
173
- return all_tiles
278
+ return tile_layers
279
+
280
+ def _filter_tiles(self, mask):
281
+ """Filter relevant dates with pandas and geopandas because fast."""
282
+ df = pd.DataFrame(self.tiles)
283
+ filt = (df["name"].notna()) & (df["year"].str.contains("|".join(self.years)))
284
+ if self.contains:
285
+ for x in self.contains:
286
+ filt &= df["name"].str.contains(x)
287
+ if self.not_contains:
288
+ for x in self.not_contains:
289
+ filt &= ~df["name"].str.contains(x)
290
+ df = df[filt]
291
+ geoms = np.where(df["geometry"].notna(), df["geometry"], df["bbox"])
292
+ geoms = GeoSeries(geoms)
293
+ assert geoms.index.is_unique
294
+ return df.iloc[sfilter(geoms, mask).index]
174
295
 
175
296
  def __post_init__(self) -> None:
176
297
  """Fix typings."""
@@ -195,7 +316,11 @@ class NorgeIBilderWms(WmsLoader):
195
316
  return
196
317
  self.tiles = [
197
318
  {
198
- key: value if key != "bbox" else shapely.wkt.loads(value)
319
+ key: (
320
+ value
321
+ if key not in ["bbox", "geometry"]
322
+ else shapely.wkt.loads(value)
323
+ )
199
324
  for key, value in tile.items()
200
325
  }
201
326
  for tile in self.tiles
@@ -45,14 +45,12 @@ class Points:
45
45
  return [0 for _ in distances]
46
46
 
47
47
  if rules.nodedist_multiplier and rules.nodedist_kmh:
48
- raise ValueError(
49
- "Can only specify one of 'nodedist_multiplier' and 'nodedist_kmh'"
50
- )
48
+ raise ValueError("Cannot set both 'nodedist_multiplier' and 'nodedist_kmh'")
51
49
 
52
50
  if rules.nodedist_multiplier:
53
- if rules.weight != "meters":
51
+ if rules.weight == "minutes":
54
52
  raise ValueError(
55
- "Can only specify 'nodedist_multiplier' when the 'weight' is meters"
53
+ "Cannot set 'nodedist_multiplier' when the 'weight' is minutes"
56
54
  )
57
55
  return [x * rules.nodedist_multiplier for x in distances]
58
56
 
sgis/raster/base.py CHANGED
@@ -38,10 +38,8 @@ def _get_transform_from_bounds(
38
38
  obj: GeoDataFrame | GeoSeries | Geometry | tuple, shape: tuple[int, ...]
39
39
  ) -> Affine:
40
40
  minx, miny, maxx, maxy = to_bbox(obj)
41
- if len(shape) == 2:
42
- height, width = shape
43
- elif len(shape) == 3:
44
- _, height, width = shape
41
+ if len(shape) in [2, 3]:
42
+ height, width = shape[-2:]
45
43
  else:
46
44
  return None
47
45
  # raise ValueError(shape)
@@ -104,7 +102,7 @@ def _array_to_geojson(
104
102
  return _array_to_geojson_loop(array, transform, mask, processes)
105
103
 
106
104
  except Exception as err:
107
- raise err.__class__(array.shape, err) from err
105
+ raise err.__class__(f"{array.shape}: {err}") from err
108
106
 
109
107
 
110
108
  def _array_to_geojson_loop(array, transform, mask, processes):
@@ -860,7 +860,6 @@ class Band(_ImageBandBase):
860
860
  self.transform = _get_transform_from_bounds(self._bounds, shape=data.shape)
861
861
  self._from_array = True
862
862
  self.values = data
863
-
864
863
  self._res = _get_res_from_bounds(self._bounds, self.values.shape)
865
864
 
866
865
  elif not isinstance(data, (str | Path | os.PathLike)):
@@ -1077,7 +1076,6 @@ class Band(_ImageBandBase):
1077
1076
  self.transform = None
1078
1077
  # activate setter
1079
1078
  self.values = self._values
1080
-
1081
1079
  return self
1082
1080
 
1083
1081
  if self.has_array and bounds_was_none:
@@ -1162,8 +1160,7 @@ class Band(_ImageBandBase):
1162
1160
  values.shape,
1163
1161
  )
1164
1162
 
1165
- width, height = values.shape[-2:]
1166
-
1163
+ height, width = values.shape[-2:]
1167
1164
  if width and height:
1168
1165
  self.transform = rasterio.transform.from_bounds(
1169
1166
  *bounds, width, height
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ssb-sgis
3
- Version: 1.2.6
3
+ Version: 1.2.8
4
4
  Summary: GIS functions used at Statistics Norway.
5
5
  Home-page: https://github.com/statisticsnorway/ssb-sgis
6
6
  License: MIT
@@ -4,13 +4,13 @@ sgis/debug_config.py,sha256=Tfr19kU46hSkkspsIJcrUWvlhaL4U3-f8xEPkujSCAQ,593
4
4
  sgis/exceptions.py,sha256=WNaEBPNNx0rmz-YDzlFX4vIE7ocJQruUTqS2RNAu2zU,660
5
5
  sgis/geopandas_tools/__init__.py,sha256=bo8lFMcltOz7TtWAi52_ekR2gd3mjfBfKeMDV5zuqFY,28
6
6
  sgis/geopandas_tools/bounds.py,sha256=YJyF0gp78hFAjLLZmDquRKCBAtbt7QouG3snTcJeNQs,23822
7
- sgis/geopandas_tools/buffer_dissolve_explode.py,sha256=ReIgoeh6CUVcLmsUZ_pyoWYg6iBZzYiGmFq6CMOKRvE,19535
7
+ sgis/geopandas_tools/buffer_dissolve_explode.py,sha256=z9HvakazR_prXH862e8-gEe7UFbeI4rRTbUaBgPeMBk,19552
8
8
  sgis/geopandas_tools/centerlines.py,sha256=Q65Sx01SeAlulBEd9oaZkB2maBBNdLcJwAbTILg4SPU,11848
9
9
  sgis/geopandas_tools/cleaning.py,sha256=fST0xFztmyn-QUOAfvjZmu7aO_zPiolWK7gd7TR6ffI,24393
10
10
  sgis/geopandas_tools/conversion.py,sha256=CrasgWHAnUmLC5tP73ZTDjQ6ahKFHQGqWj86PUif24M,24176
11
11
  sgis/geopandas_tools/duplicates.py,sha256=TDDM4u1n7SIkyJrOfl1Lno92AmUPqtXBHsj1IUKC0hI,14992
12
12
  sgis/geopandas_tools/general.py,sha256=YRpNEdwTHyFdQOdAfbCmYXS7PxoDjXxoagwpteXkYdI,43937
13
- sgis/geopandas_tools/geocoding.py,sha256=n47aFQMm4yX1MsPnTM4dFjwegCA1ZmGUDj1uyu7OJV4,691
13
+ sgis/geopandas_tools/geocoding.py,sha256=sZjUW52ULhQWDLmU51C9_itBePkDuWkp8swvYaiYmJk,679
14
14
  sgis/geopandas_tools/geometry_types.py,sha256=ijQDbQaZPqPGjBl707H4yooNXpk21RXyatI7itnvqLk,7603
15
15
  sgis/geopandas_tools/neighbors.py,sha256=qTvnOyQyrcWQd0BDrmOvFQd8csMh005e_idJGmB4g7k,17485
16
16
  sgis/geopandas_tools/overlay.py,sha256=5i9u8GgFuU0fCqzELsbIaoUPhw-E7eZHl_yKB0wEcGM,23464
@@ -18,7 +18,7 @@ sgis/geopandas_tools/point_operations.py,sha256=JM4hvfIVxZaZdGNlGzcCurrKzkgC_b9h
18
18
  sgis/geopandas_tools/polygon_operations.py,sha256=v-B9IgbFfm4dVHKPyzvmnNiqVCdtl9ddpCsQpZZ-9sU,49284
19
19
  sgis/geopandas_tools/polygons_as_rings.py,sha256=BX_GZS6F9I4NbEpiOlNBd7zywJjdfdJVi_MkeONBuiM,14941
20
20
  sgis/geopandas_tools/runners.py,sha256=J4lH0RXYDYTLVeQFgNv8gEY0E97QGIQ4zPW5vfoxgDU,12979
21
- sgis/geopandas_tools/sfilter.py,sha256=BPz6-_9B7QdyYmVatZXavdHj7FIW_ztIyJHQOkKJt7A,10284
21
+ sgis/geopandas_tools/sfilter.py,sha256=CZ_-c4t1CQCwJ7RHCKo1Na9u-aAg18xXnJAMiUqoaj8,10411
22
22
  sgis/geopandas_tools/utils.py,sha256=X0pRvB1tWgV_0BCrRS1HU9LtLGnZCpvVPxyqM9JGb0Y,1415
23
23
  sgis/helpers.py,sha256=4N6vFWQ3TYVzRHNcWY_fNa_GkFuaZB3vtCkkFND-qs0,9628
24
24
  sgis/io/__init__.py,sha256=uyBr20YDqB2bQttrd5q1JuGOvX32A-MSvS7Wmw5f5qg,177
@@ -28,19 +28,19 @@ sgis/io/opener.py,sha256=HWO3G1NB6bpXKM94JadCD513vjat1o1TFjWGWzyVasg,898
28
28
  sgis/io/read_parquet.py,sha256=FvZYv1rLkUlrSaUY6QW6E1yntmntTeQuZ9ZRgCDO4IM,3776
29
29
  sgis/maps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
30
  sgis/maps/examine.py,sha256=Pb0dH8JazU5E2svfQrzHO1Bi-sjy5SeyY6zoeMO34jE,9369
31
- sgis/maps/explore.py,sha256=A6-i0uKYIdfS46zrPIURObJqmt2VuQjXyS8FVk58cHU,47657
31
+ sgis/maps/explore.py,sha256=azfNNcEEiNp2lJxWN1Emf7kcmG60WL_ok_ilMw0-IL8,47914
32
32
  sgis/maps/httpserver.py,sha256=TETSGOgLjKl3TquPGoIP0tCJCz7BIwmXrrzSCT7jhXE,2550
33
33
  sgis/maps/legend.py,sha256=qq2RkebuaNAdFztlXrDOWbN0voeK5w5VycmRKyx0NdM,26512
34
- sgis/maps/map.py,sha256=WZ5JnCpdioBCEh6kmV3XB4xVw41fYsEmQ6v8MIfwzmY,30727
35
- sgis/maps/maps.py,sha256=Zkp-UGj92BCFYhY1_TLXL4FjnvwOjGMAryoWCtFdwPk,22989
36
- sgis/maps/norge_i_bilder.json,sha256=VKmb7rg4jvgc8_Ve1fFnHyZ_Dkv4T5GTA0UCpqpFAi4,492751
34
+ sgis/maps/map.py,sha256=XWf3QJ6a4gZno2NziK1dKLRktJGGr-vn6eHudBlW9Uc,30758
35
+ sgis/maps/maps.py,sha256=fLK5WUlQ2YTm7t-8260lYxCFvpZN6j0Y-bVYCyv8NAY,23249
36
+ sgis/maps/norge_i_bilder.json,sha256=G9DIN_2vyn-18UF5wUC-koZxFCbiNxMu0BbCJhMFJUk,15050340
37
37
  sgis/maps/thematicmap.py,sha256=Z3o_Bca0oty5Cn35pZfX5Qy52sXDVIMVSFD6IlZrovo,25111
38
38
  sgis/maps/tilesources.py,sha256=F4mFHxPwkiPJdVKzNkScTX6xbJAMIUtlTq4mQ83oguw,1746
39
- sgis/maps/wms.py,sha256=LSBtKkG5d-sggK_qO8BvOHBvPZZV_7AAo25kHF6kPio,6933
39
+ sgis/maps/wms.py,sha256=oB7jeE3rSRhM-xz7t95hFLjtuG18mw7CV4wNx6IuBes,12001
40
40
  sgis/networkanalysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  sgis/networkanalysis/_get_route.py,sha256=dMX4Vm6O90ISIZPjQWuZMVMuEubkeSdC2osMCbFvrRU,7750
42
42
  sgis/networkanalysis/_od_cost_matrix.py,sha256=zkyPX7ObT996ahaFJ2oI0D0SqQWbWyfy_qLtXwValPg,3434
43
- sgis/networkanalysis/_points.py,sha256=ajCy17dAmRq3bWRkNu_0LHreCVJ5Uh8DzAKWxyw7ipw,4481
43
+ sgis/networkanalysis/_points.py,sha256=128QEepBGAyI5XakMUVvNyOnJE0Ts7hvGiVUt1YTXiU,4439
44
44
  sgis/networkanalysis/_service_area.py,sha256=jE0X54yS4eMfZYJXeKe_NgMKPDpau-05xWZaxDi_c6Y,5546
45
45
  sgis/networkanalysis/closing_network_holes.py,sha256=FYZ677nRwLmDkP6bQ1ssQ_h29RzAG463U4xmbu5ksfg,14572
46
46
  sgis/networkanalysis/cutting_lines.py,sha256=ZQAt0cufaPeNAEqUzp-imu26AIL9S5-lw6Xifa8RoWk,9818
@@ -55,13 +55,13 @@ sgis/parallel/__init__.py,sha256=fw_Fl3IJk1bKzrRBhZIoOpznJqwd09NVHJJFj2ZLeIU,32
55
55
  sgis/parallel/parallel.py,sha256=V7O5mEZdfJpcOPrmn2H4bEGtbzA0FggjQ8dGhznjr80,40052
56
56
  sgis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
57
  sgis/raster/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
- sgis/raster/base.py,sha256=tiZEuMcVK6hOm_aIjWhQ1WGshcjsxT1fFkuBSLFiMC0,7785
59
- sgis/raster/image_collection.py,sha256=gbC0V2Xmckrsi1iAKbYgrsb_f9rja6Y7QUqMMJVCy2Y,121700
58
+ sgis/raster/base.py,sha256=8JdXXDj8CgJQt5WIkkNbpM5U0pYyQrWQY9dszfUaUQ4,7743
59
+ sgis/raster/image_collection.py,sha256=H7d9c6f-LsGXBK8oCpWBlgd2zbLxYvfNMYllnbrO_rk,121697
60
60
  sgis/raster/indices.py,sha256=efJmgfPg_VuSzXFosXV661IendF8CwPFWtMhyP4TMUg,222
61
61
  sgis/raster/regex.py,sha256=4idTJ9vFtsGtbxcjJrx2VrpJJuDMP3bLdqF93Vc_cmY,3752
62
62
  sgis/raster/sentinel_config.py,sha256=nySDqn2R8M6W8jguoBeSAK_zzbAsqmaI59i32446FwY,1268
63
63
  sgis/raster/zonal.py,sha256=D4Gyptw-yOLTCO41peIuYbY-DANsJCG19xXDlf1QAz4,2299
64
- ssb_sgis-1.2.6.dist-info/LICENSE,sha256=np3IfD5m0ZUofn_kVzDZqliozuiO6wrktw3LRPjyEiI,1073
65
- ssb_sgis-1.2.6.dist-info/METADATA,sha256=1g2k5KcE4NTLcxfNqL08atchi_udhavHB7YLWfLrbew,11740
66
- ssb_sgis-1.2.6.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
67
- ssb_sgis-1.2.6.dist-info/RECORD,,
64
+ ssb_sgis-1.2.8.dist-info/LICENSE,sha256=np3IfD5m0ZUofn_kVzDZqliozuiO6wrktw3LRPjyEiI,1073
65
+ ssb_sgis-1.2.8.dist-info/METADATA,sha256=3bsjQU53D8bZVZ7J2VgZDeUeB0wP6hhnXJBKsvLz18M,11740
66
+ ssb_sgis-1.2.8.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
67
+ ssb_sgis-1.2.8.dist-info/RECORD,,