ssb-sgis 1.0.14__tar.gz → 1.1.0__tar.gz

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.
Files changed (62) hide show
  1. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/PKG-INFO +1 -1
  2. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/pyproject.toml +1 -1
  3. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/__init__.py +1 -1
  4. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/bounds.py +1 -0
  5. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/buffer_dissolve_explode.py +9 -9
  6. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/io/dapla_functions.py +10 -10
  7. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/maps/explore.py +11 -15
  8. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/maps/maps.py +12 -18
  9. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/maps/thematicmap.py +9 -2
  10. ssb_sgis-1.0.14/src/sgis/maps/norge_i_bilder_wms.py → ssb_sgis-1.1.0/src/sgis/maps/wms.py +23 -1
  11. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/parallel/parallel.py +5 -5
  12. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/LICENSE +0 -0
  13. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/README.md +0 -0
  14. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/debug_config.py +0 -0
  15. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/exceptions.py +0 -0
  16. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/__init__.py +0 -0
  17. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/centerlines.py +0 -0
  18. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/cleaning.py +0 -0
  19. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/conversion.py +0 -0
  20. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/duplicates.py +0 -0
  21. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/general.py +0 -0
  22. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/geocoding.py +0 -0
  23. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/geometry_types.py +0 -0
  24. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/neighbors.py +0 -0
  25. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/overlay.py +0 -0
  26. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/point_operations.py +0 -0
  27. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/polygon_operations.py +0 -0
  28. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/polygons_as_rings.py +0 -0
  29. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/geopandas_tools/sfilter.py +0 -0
  30. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/helpers.py +0 -0
  31. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/io/_is_dapla.py +0 -0
  32. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/io/opener.py +0 -0
  33. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/io/read_parquet.py +0 -0
  34. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/maps/__init__.py +0 -0
  35. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/maps/examine.py +0 -0
  36. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/maps/httpserver.py +0 -0
  37. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/maps/legend.py +0 -0
  38. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/maps/map.py +0 -0
  39. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/maps/norge_i_bilder.json +0 -0
  40. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/maps/tilesources.py +0 -0
  41. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/__init__.py +0 -0
  42. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/_get_route.py +0 -0
  43. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/_od_cost_matrix.py +0 -0
  44. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/_points.py +0 -0
  45. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/_service_area.py +0 -0
  46. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/closing_network_holes.py +0 -0
  47. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/cutting_lines.py +0 -0
  48. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/directednetwork.py +0 -0
  49. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/finding_isolated_networks.py +0 -0
  50. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/network.py +0 -0
  51. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/networkanalysis.py +0 -0
  52. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/networkanalysisrules.py +0 -0
  53. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/nodes.py +0 -0
  54. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/networkanalysis/traveling_salesman.py +0 -0
  55. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/py.typed +0 -0
  56. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/raster/__init__.py +0 -0
  57. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/raster/base.py +0 -0
  58. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/raster/image_collection.py +0 -0
  59. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/raster/indices.py +0 -0
  60. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/raster/regex.py +0 -0
  61. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/raster/sentinel_config.py +0 -0
  62. {ssb_sgis-1.0.14 → ssb_sgis-1.1.0}/src/sgis/raster/zonal.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ssb-sgis
3
- Version: 1.0.14
3
+ Version: 1.1.0
4
4
  Summary: GIS functions used at Statistics Norway.
5
5
  Home-page: https://github.com/statisticsnorway/ssb-sgis
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "ssb-sgis"
3
- version = "1.0.14"
3
+ version = "1.1.0"
4
4
  description = "GIS functions used at Statistics Norway."
5
5
  authors = ["Morten Letnes <morten.letnes@ssb.no>"]
6
6
  license = "MIT"
@@ -96,10 +96,10 @@ from .maps.maps import explore
96
96
  from .maps.maps import explore_locals
97
97
  from .maps.maps import qtm
98
98
  from .maps.maps import samplemap
99
- from .maps.norge_i_bilder_wms import NorgeIBilderWms
100
99
  from .maps.thematicmap import ThematicMap
101
100
  from .maps.tilesources import kartverket as kartverket_tiles
102
101
  from .maps.tilesources import xyz as xyztiles
102
+ from .maps.wms import NorgeIBilderWms
103
103
  from .networkanalysis.closing_network_holes import close_network_holes
104
104
  from .networkanalysis.closing_network_holes import close_network_holes_to_deadends
105
105
  from .networkanalysis.closing_network_holes import get_k_nearest_points_for_deadends
@@ -669,6 +669,7 @@ def bounds_to_points(
669
669
  0 MULTIPOINT (1.00000 0.00000, 1.00000 1.00000, ...
670
670
  1 MULTIPOINT (0.00000 0.00000)
671
671
  """
672
+ gdf = gdf.copy() if copy else gdf
672
673
  as_bounds = bounds_to_polygon(gdf, copy=copy)
673
674
  if isinstance(gdf, GeoSeries):
674
675
  return GeoSeries(extract_unique_points(as_bounds), index=gdf.index)
@@ -5,7 +5,7 @@ for the following:
5
5
 
6
6
  - Geometries are made valid after buffer and dissolve.
7
7
 
8
- - The buffer resolution defaults to 50 (geopandas' default is 16).
8
+ - The buffer resolution defaults to 30 (geopandas' default is 16).
9
9
 
10
10
  - If 'by' is not specified, the index will be labeled 0, 1, …, n - 1 after exploded, instead of 0, 0, …, 0 as it will with the geopandas defaults.
11
11
 
@@ -49,7 +49,7 @@ def buffdissexp(
49
49
  gdf: GeoDataFrame,
50
50
  distance: int | float,
51
51
  *,
52
- resolution: int = 50,
52
+ resolution: int = 30,
53
53
  index_parts: bool = False,
54
54
  copy: bool = True,
55
55
  grid_size: float | int | None = None,
@@ -68,7 +68,7 @@ def buffdissexp(
68
68
  distance: the distance (meters, degrees, depending on the crs) to buffer
69
69
  the geometry by
70
70
  resolution: The number of segments used to approximate a quarter circle.
71
- Here defaults to 50, as opposed to the default 16 in geopandas.
71
+ Here defaults to 30, as opposed to the default 16 in geopandas.
72
72
  index_parts: If False (default), the index after dissolve is respected. If
73
73
  True, an integer index level is added during explode.
74
74
  copy: Whether to copy the GeoDataFrame before buffering. Defaults to True.
@@ -101,7 +101,7 @@ def buffdissexp(
101
101
  def buffdiss(
102
102
  gdf: GeoDataFrame,
103
103
  distance: int | float,
104
- resolution: int = 50,
104
+ resolution: int = 30,
105
105
  copy: bool = True,
106
106
  n_jobs: int = 1,
107
107
  join_style: int | str = "round",
@@ -119,7 +119,7 @@ def buffdiss(
119
119
  distance: the distance (meters, degrees, depending on the crs) to buffer
120
120
  the geometry by
121
121
  resolution: The number of segments used to approximate a quarter circle.
122
- Here defaults to 50, as opposed to the default 16 in geopandas.
122
+ Here defaults to 30, as opposed to the default 16 in geopandas.
123
123
  join_style: Buffer join style.
124
124
  copy: Whether to copy the GeoDataFrame before buffering. Defaults to True.
125
125
  n_jobs: Number of threads to use. Defaults to 1.
@@ -511,7 +511,7 @@ def buffdissexp_by_cluster(
511
511
  gdf: GeoDataFrame,
512
512
  distance: int | float,
513
513
  *,
514
- resolution: int = 50,
514
+ resolution: int = 30,
515
515
  copy: bool = True,
516
516
  n_jobs: int = 1,
517
517
  join_style: int | str = "round",
@@ -532,7 +532,7 @@ def buffdissexp_by_cluster(
532
532
  distance: the distance (meters, degrees, depending on the crs) to buffer
533
533
  the geometry by
534
534
  resolution: The number of segments used to approximate a quarter circle.
535
- Here defaults to 50, as opposed to the default 16 in geopandas.
535
+ Here defaults to 30, as opposed to the default 16 in geopandas.
536
536
  join_style: Buffer join style.
537
537
  copy: Whether to copy the GeoDataFrame before buffering. Defaults to True.
538
538
  n_jobs: int = 1,
@@ -554,7 +554,7 @@ def buffdissexp_by_cluster(
554
554
  def buff(
555
555
  gdf: GeoDataFrame | GeoSeries,
556
556
  distance: int | float,
557
- resolution: int = 50,
557
+ resolution: int = 30,
558
558
  copy: bool = True,
559
559
  join_style: int | str = "round",
560
560
  **buffer_kwargs,
@@ -566,7 +566,7 @@ def buff(
566
566
  distance: the distance (meters, degrees, depending on the crs) to buffer
567
567
  the geometry by
568
568
  resolution: The number of segments used to approximate a quarter circle.
569
- Here defaults to 50, as opposed to the default 16 in geopandas.
569
+ Here defaults to 30, as opposed to the default 16 in geopandas.
570
570
  join_style: Buffer join style.
571
571
  copy: Whether to copy the GeoDataFrame before buffering. Defaults to True.
572
572
  **buffer_kwargs: additional keyword arguments passed to geopandas' buffer.
@@ -15,6 +15,7 @@ import pandas as pd
15
15
  import pyarrow
16
16
  import pyarrow.parquet as pq
17
17
  import shapely
18
+ from gcsfs import GCSFileSystem
18
19
  from geopandas import GeoDataFrame
19
20
  from geopandas import GeoSeries
20
21
  from geopandas.io.arrow import _geopandas_to_arrow
@@ -30,7 +31,7 @@ PANDAS_FALLBACK_INFO = " Set pandas_fallback=True to ignore this error."
30
31
  def read_geopandas(
31
32
  gcs_path: str | Path | list[str | Path] | tuple[str | Path] | GeoSeries,
32
33
  pandas_fallback: bool = False,
33
- file_system: dp.gcs.GCSFileSystem | None = None,
34
+ file_system: GCSFileSystem | None = None,
34
35
  mask: GeoSeries | GeoDataFrame | shapely.Geometry | tuple | None = None,
35
36
  threads: int | None = None,
36
37
  **kwargs,
@@ -138,8 +139,7 @@ def read_geopandas(
138
139
  raise e.__class__(
139
140
  f"{e.__class__.__name__}: {e} for {gcs_path}."
140
141
  ) from e
141
- df = dp.read_pandas(gcs_path, **kwargs)
142
-
142
+ df = pd.read_parquet(file, **kwargs)
143
143
  if pandas_fallback or not len(df):
144
144
  return df
145
145
  else:
@@ -157,7 +157,7 @@ def read_geopandas(
157
157
  except ValueError as e:
158
158
  if "Missing geo metadata" not in str(e) and "geometry" not in str(e):
159
159
  raise e
160
- df = dp.read_pandas(gcs_path, **kwargs)
160
+ df = pd.read_parquet(file, **kwargs)
161
161
 
162
162
  if pandas_fallback or not len(df):
163
163
  return df
@@ -168,7 +168,7 @@ def read_geopandas(
168
168
  ) from e
169
169
  except Exception as e:
170
170
  raise e.__class__(
171
- f"{e.__class__.__name__}: {e} for {df}." + more_txt
171
+ f"{e.__class__.__name__}: {e} for {gcs_path}." + more_txt
172
172
  ) from e
173
173
 
174
174
  if mask is not None:
@@ -177,7 +177,7 @@ def read_geopandas(
177
177
 
178
178
 
179
179
  def _get_bounds_parquet(
180
- path: str | Path, file_system: dp.gcs.GCSFileSystem, pandas_fallback: bool = False
180
+ path: str | Path, file_system: GCSFileSystem, pandas_fallback: bool = False
181
181
  ) -> tuple[list[float], dict] | tuple[None, None]:
182
182
  with file_system.open(path) as f:
183
183
  try:
@@ -202,7 +202,7 @@ def _get_bounds_parquet(
202
202
  return meta["bbox"], meta["crs"]
203
203
 
204
204
 
205
- def _get_columns(path: str | Path, file_system: dp.gcs.GCSFileSystem) -> pd.Index:
205
+ def _get_columns(path: str | Path, file_system: GCSFileSystem) -> pd.Index:
206
206
  with file_system.open(path) as f:
207
207
  schema = pq.read_schema(f)
208
208
  index_cols = _get_index_cols(schema)
@@ -216,7 +216,7 @@ def _get_index_cols(schema: pyarrow.Schema) -> list[str]:
216
216
 
217
217
  def get_bounds_series(
218
218
  paths: list[str | Path] | tuple[str | Path],
219
- file_system: dp.gcs.GCSFileSystem | None = None,
219
+ file_system: GCSFileSystem | None = None,
220
220
  threads: int | None = None,
221
221
  pandas_fallback: bool = False,
222
222
  ) -> GeoSeries:
@@ -227,7 +227,7 @@ def get_bounds_series(
227
227
 
228
228
  Args:
229
229
  paths: Iterable of file paths in gcs.
230
- file_system: Optional instance of dp.gcs.GCSFileSystem.
230
+ file_system: Optional instance of GCSFileSystem.
231
231
  If None, an instance is created within the function.
232
232
  Note that this is slower in long loops.
233
233
  threads: Number of threads to use if reading multiple files. Defaults to
@@ -307,7 +307,7 @@ def write_geopandas(
307
307
  gcs_path: str | Path,
308
308
  overwrite: bool = True,
309
309
  pandas_fallback: bool = False,
310
- file_system: dp.gcs.GCSFileSystem | None = None,
310
+ file_system: GCSFileSystem | None = None,
311
311
  write_covering_bbox: bool = False,
312
312
  **kwargs,
313
313
  ) -> None:
@@ -44,7 +44,7 @@ from ..geopandas_tools.general import clean_geoms
44
44
  from ..geopandas_tools.general import make_all_singlepart
45
45
  from ..geopandas_tools.geometry_types import get_geom_type
46
46
  from ..geopandas_tools.geometry_types import to_single_geom_type
47
- from .norge_i_bilder_wms import NorgeIBilderWms
47
+ from .wms import WmsLoader
48
48
 
49
49
  try:
50
50
  from ..raster.image_collection import Band
@@ -280,7 +280,7 @@ class Explore(Map):
280
280
  max_images: int = 10,
281
281
  max_nodata_percentage: int = 100,
282
282
  display: bool = True,
283
- norge_i_bilder: bool = False,
283
+ wms: WmsLoader | None = None,
284
284
  **kwargs,
285
285
  ) -> None:
286
286
  """Initialiser.
@@ -310,9 +310,7 @@ class Explore(Map):
310
310
  max_nodata_percentage: Maximum percentage nodata values (e.g. clouds) ro allow in
311
311
  image arrays.
312
312
  display: Whether to display the map interactively.
313
- norge_i_bilder: If True, all Norge i bilder images in bounds will be loaded
314
- into the map. Can optionally be set to an instance of NorgeIBilderWms to filter
315
- years and names.
313
+ wms: A WmsLoader instance for loading image tiles as layers. E.g. NorgeIBilderWms.
316
314
  **kwargs: Additional keyword arguments. Can also be geometry-like objects
317
315
  where the key is the label.
318
316
  """
@@ -329,7 +327,7 @@ class Explore(Map):
329
327
  self.max_images = max_images
330
328
  self.max_nodata_percentage = max_nodata_percentage
331
329
  self.display = display
332
- self.norge_i_bilder = norge_i_bilder
330
+ self.wms = [wms] if isinstance(wms, WmsLoader) else wms
333
331
  self.legend = None
334
332
 
335
333
  self.browser = browser
@@ -768,13 +766,11 @@ class Explore(Map):
768
766
  for tile in tiles:
769
767
  to_tile(tile, max_zoom=self.max_zoom).add_to(mapobj)
770
768
 
771
- def _add_norge_i_bilder(self, map_: folium.Map, bbox: Any) -> None:
772
- if not isinstance(self.norge_i_bilder, NorgeIBilderWms):
773
- self.norge_i_bilder = NorgeIBilderWms()
774
-
775
- tiles = self.norge_i_bilder.get_tiles(bbox, max_zoom=self.max_zoom)
776
- for tile in tiles.values():
777
- map_.add_child(tile)
769
+ def _add_wms(self, map_: folium.Map, bbox: Any) -> None:
770
+ for wms in self.wms:
771
+ tiles = wms.get_tiles(bbox, max_zoom=self.max_zoom)
772
+ for tile in tiles.values():
773
+ map_.add_child(tile)
778
774
 
779
775
  def _create_continous_map(self):
780
776
  self._prepare_continous_map()
@@ -982,8 +978,8 @@ class Explore(Map):
982
978
  m.get_root().add_child(style)
983
979
  # folium.LayerControl(collapsed=False).add_to(m)
984
980
 
985
- if self.norge_i_bilder:
986
- self._add_norge_i_bilder(m, bounds)
981
+ if self.wms:
982
+ self._add_wms(m, bounds)
987
983
 
988
984
  return m
989
985
 
@@ -31,8 +31,8 @@ from ..geopandas_tools.geocoding import address_to_gdf
31
31
  from ..geopandas_tools.geometry_types import get_geom_type
32
32
  from .explore import Explore
33
33
  from .map import Map
34
- from .norge_i_bilder_wms import NorgeIBilderWms
35
34
  from .thematicmap import ThematicMap
35
+ from .wms import WmsLoader
36
36
 
37
37
  try:
38
38
  from torchgeo.datasets.geo import RasterDataset
@@ -91,7 +91,7 @@ def explore(
91
91
  size: int | None = None,
92
92
  max_images: int = 10,
93
93
  max_nodata_percentage: int = 100,
94
- norge_i_bilder: bool | NorgeIBilderWms = False,
94
+ wms: WmsLoader | None = None,
95
95
  **kwargs,
96
96
  ) -> Explore:
97
97
  """Interactive map of GeoDataFrames with layers that can be toggled on/off.
@@ -123,9 +123,7 @@ def explore(
123
123
  map. Defaults to 10.
124
124
  max_nodata_percentage: Maximum percentage nodata values (e.g. clouds) ro allow in
125
125
  image arrays.
126
- norge_i_bilder: If True, all Norge i bilder images in bounds will be loaded
127
- into the map. Can optionally be set to an instance of NorgeIBilderWms to filter
128
- years and names.
126
+ wms: A WmsLoader instance for loading image tiles as layers. E.g. NorgeIBilderWms.
129
127
  **kwargs: Keyword arguments to pass to geopandas.GeoDataFrame.explore, for
130
128
  instance 'cmap' to change the colors, 'scheme' to change how the data
131
129
  is grouped. This defaults to 'fisherjenkssampled' for numeric data.
@@ -175,7 +173,7 @@ def explore(
175
173
  max_zoom=max_zoom,
176
174
  max_images=max_images,
177
175
  max_nodata_percentage=max_nodata_percentage,
178
- norge_i_bilder=norge_i_bilder,
176
+ wms=wms,
179
177
  **kwargs,
180
178
  )
181
179
 
@@ -233,7 +231,7 @@ def explore(
233
231
  max_zoom=max_zoom,
234
232
  max_images=max_images,
235
233
  max_nodata_percentage=max_nodata_percentage,
236
- norge_i_bilder=norge_i_bilder,
234
+ wms=wms,
237
235
  **kwargs,
238
236
  )
239
237
 
@@ -245,7 +243,7 @@ def explore(
245
243
  smooth_factor=smooth_factor,
246
244
  max_images=max_images,
247
245
  max_nodata_percentage=max_nodata_percentage,
248
- norge_i_bilder=norge_i_bilder,
246
+ wms=wms,
249
247
  **kwargs,
250
248
  )
251
249
 
@@ -271,7 +269,7 @@ def samplemap(
271
269
  browser: bool = False,
272
270
  max_images: int = 10,
273
271
  max_nodata_percentage: int = 100,
274
- norge_i_bilder: bool | NorgeIBilderWms = False,
272
+ wms: WmsLoader | None = None,
275
273
  **kwargs,
276
274
  ) -> Explore:
277
275
  """Shows an interactive map of a random area of GeoDataFrames.
@@ -307,9 +305,7 @@ def samplemap(
307
305
  map. Defaults to 10.
308
306
  max_nodata_percentage: Maximum percentage nodata values (e.g. clouds) ro allow in
309
307
  image arrays.
310
- norge_i_bilder: If True, all Norge i bilder images in bounds will be loaded
311
- into the map. Can optionally be set to an instance of NorgeIBilderWms to filter
312
- years and names.
308
+ wms: A WmsLoader instance for loading image tiles as layers. E.g. NorgeIBilderWms.
313
309
  **kwargs: Keyword arguments to pass to geopandas.GeoDataFrame.explore, for
314
310
  instance 'cmap' to change the colors, 'scheme' to change how the data
315
311
  is grouped. This defaults to 'fisherjenkssampled' for numeric data.
@@ -393,7 +389,7 @@ def samplemap(
393
389
  smooth_factor=smooth_factor,
394
390
  max_images=max_images,
395
391
  max_nodata_percentage=max_nodata_percentage,
396
- norge_i_bilder=norge_i_bilder,
392
+ wms=wms,
397
393
  **kwargs,
398
394
  )
399
395
 
@@ -408,7 +404,7 @@ def clipmap(
408
404
  browser: bool = False,
409
405
  max_images: int = 10,
410
406
  max_nodata_percentage: int = 100,
411
- norge_i_bilder: bool | NorgeIBilderWms = False,
407
+ wms: WmsLoader | None = None,
412
408
  **kwargs,
413
409
  ) -> Explore | Map:
414
410
  """Shows an interactive map of a of GeoDataFrames clipped to the mask extent.
@@ -439,9 +435,7 @@ def clipmap(
439
435
  map. Defaults to 10.
440
436
  max_nodata_percentage: Maximum percentage nodata values (e.g. clouds) ro allow in
441
437
  image arrays.
442
- norge_i_bilder: If True, all Norge i bilder images in bounds will be loaded
443
- into the map. Can optionally be set to an instance of NorgeIBilderWms to filter
444
- years and names.
438
+ wms: A WmsLoader instance for loading image tiles as layers. E.g. NorgeIBilderWms.
445
439
  **kwargs: Keyword arguments to pass to geopandas.GeoDataFrame.explore, for
446
440
  instance 'cmap' to change the colors, 'scheme' to change how the data
447
441
  is grouped. This defaults to 'fisherjenkssampled' for numeric data.
@@ -477,7 +471,7 @@ def clipmap(
477
471
  smooth_factor=smooth_factor,
478
472
  max_images=max_images,
479
473
  max_nodata_percentage=max_nodata_percentage,
480
- norge_i_bilder=norge_i_bilder,
474
+ wms=wms,
481
475
  **kwargs,
482
476
  )
483
477
  m.mask = mask
@@ -280,7 +280,10 @@ class ThematicMap(Map):
280
280
  return self
281
281
 
282
282
  def add_background(
283
- self, gdf: GeoDataFrame, color: str | None = None
283
+ self,
284
+ gdf: GeoDataFrame,
285
+ color: str | None = None,
286
+ **kwargs,
284
287
  ) -> "ThematicMap":
285
288
  """Add a GeoDataFrame as a background layer.
286
289
 
@@ -288,6 +291,7 @@ class ThematicMap(Map):
288
291
  gdf: a GeoDataFrame.
289
292
  color: Single color. Defaults to gray (shade depends on whether the map
290
293
  facecolor is black or white).
294
+ **kwargs: Keyword arguments sent to GeoDataFrame.plot.
291
295
  """
292
296
  if color:
293
297
  self.bg_gdf_color = color
@@ -299,6 +303,7 @@ class ThematicMap(Map):
299
303
  )
300
304
  if self.bounds is None:
301
305
  self.bounds = to_bbox(self._gdf.total_bounds)
306
+ self.bg_gdf_kwargs = kwargs
302
307
  return self
303
308
 
304
309
  def plot(self, **kwargs) -> None:
@@ -515,7 +520,9 @@ class ThematicMap(Map):
515
520
  def _actually_add_background(self) -> None:
516
521
  self.ax.set_xlim([self.minx - self.diffx * 0.03, self.maxx + self.diffx * 0.03])
517
522
  self.ax.set_ylim([self.miny - self.diffy * 0.03, self.maxy + self.diffy * 0.03])
518
- self._background_gdfs.plot(ax=self.ax, color=self.bg_gdf_color)
523
+ self._background_gdfs.plot(
524
+ ax=self.ax, color=self.bg_gdf_color, **self.bg_gdf_kwargs
525
+ )
519
526
 
520
527
  @staticmethod
521
528
  def _get_matplotlib_figure_and_axix(
@@ -1,3 +1,4 @@
1
+ import abc
1
2
  import datetime
2
3
  import json
3
4
  import re
@@ -24,7 +25,28 @@ DEFAULT_YEARS: tuple[str] = tuple(
24
25
 
25
26
 
26
27
  @dataclass
27
- class NorgeIBilderWms:
28
+ class WmsLoader(abc.ABC):
29
+ """Abstract base class for wms loaders.
30
+
31
+ Child classes must implement the method 'get_tiles',
32
+ which should return a list of folium.WmsTileLayer.
33
+ """
34
+
35
+ @abc.abstractmethod
36
+ def get_tiles(self, bbox: Any, max_zoom: int = 40) -> list[folium.WmsTileLayer]:
37
+ """Get all tiles intersecting with a bbox."""
38
+
39
+ @abc.abstractmethod
40
+ def load_tiles(self) -> None:
41
+ """Load all tiles into self.tiles.
42
+
43
+ Not needed in sgis.explore.
44
+ """
45
+ pass
46
+
47
+
48
+ @dataclass
49
+ class NorgeIBilderWms(WmsLoader):
28
50
  """Loads Norge i bilder tiles as folium.WmsTiles."""
29
51
 
30
52
  years: Iterable[int | str] = DEFAULT_YEARS
@@ -590,7 +590,7 @@ class Parallel:
590
590
  with_neighbors: bool = False,
591
591
  funcdict: dict[str, Callable] | None = None,
592
592
  file_type: str = "parquet",
593
- muni_number_col: str = "KOMMUNENR",
593
+ muni_number_col: str = "komm_nr",
594
594
  strict: bool = False,
595
595
  write_empty: bool = False,
596
596
  id_assign_func: Callable | functools.partial = clean_overlay,
@@ -622,7 +622,7 @@ class Parallel:
622
622
  the data is read.
623
623
  file_type: Defaults to parquet.
624
624
  muni_number_col: String column name with municipality
625
- number/identifier. Defaults to KOMMUNENR. If the column is not present
625
+ number/identifier. Defaults to komm_nr. If the column is not present
626
626
  in the data to be split, the data will be intersected with the
627
627
  municipalities.
628
628
  strict: If False (default), the dictionaries 'out_data' and 'funcdict' does
@@ -761,7 +761,7 @@ def write_municipality_data(
761
761
  out_folder: str,
762
762
  municipalities: GeoDataFrame | list[str] | None = None,
763
763
  with_neighbors: bool = False,
764
- muni_number_col: str = "KOMMUNENR",
764
+ muni_number_col: str = "komm_nr",
765
765
  file_type: str = "parquet",
766
766
  func: Callable | None = None,
767
767
  write_empty: bool = False,
@@ -840,7 +840,7 @@ def _write_municipality_data(
840
840
  data: str | GeoDataFrame | DataFrame,
841
841
  out_folder: str,
842
842
  municipalities: GeoDataFrame | list[str] | None = None,
843
- muni_number_col: str = "KOMMUNENR",
843
+ muni_number_col: str = "komm_nr",
844
844
  file_type: str = "parquet",
845
845
  func: Callable | None = None,
846
846
  write_empty: bool = False,
@@ -896,7 +896,7 @@ def _write_neighbor_municipality_data(
896
896
  data: str | GeoDataFrame | DataFrame,
897
897
  out_folder: str,
898
898
  municipalities: GeoDataFrame,
899
- muni_number_col: str = "KOMMUNENR",
899
+ muni_number_col: str = "komm_nr",
900
900
  file_type: str = "parquet",
901
901
  func: Callable | None = None,
902
902
  write_empty: bool = False,
File without changes
File without changes
File without changes
File without changes
File without changes