ssb-sgis 1.2.14__py3-none-any.whl → 1.2.16__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.
@@ -507,7 +507,7 @@ def to_gdf(
507
507
  geoseries = GeoSeries(_make_shapely_geoms(obj.iloc[:, 0]), index=index)
508
508
  return GeoDataFrame({key: geoseries}, geometry=key, crs=crs, **kwargs)
509
509
 
510
- if geometry and geom_col not in obj or isinstance(obj, pd.DataFrame):
510
+ if (geometry and geom_col not in obj) or isinstance(obj, pd.DataFrame):
511
511
  raise ValueError("Cannot find geometry column(s)", geometry)
512
512
 
513
513
  # geojson, __geo_interface__
@@ -595,10 +595,8 @@ def is_nested_geojson(obj: Any) -> bool:
595
595
 
596
596
  def get_crs_from_dict(obj: Any) -> CRS | None | Any:
597
597
  """Try to extract the 'crs' attribute of the object or an object in the object."""
598
- if (
599
- not hasattr(obj, "__iter__")
600
- or not is_dict_like(obj)
601
- and not is_dict_like(obj[0])
598
+ if not hasattr(obj, "__iter__") or (
599
+ not is_dict_like(obj) and not is_dict_like(obj[0])
602
600
  ):
603
601
  return None
604
602
 
@@ -92,7 +92,11 @@ def read_geopandas(
92
92
  if isinstance(gcs_path, (Path | os.PathLike)):
93
93
  gcs_path = str(gcs_path)
94
94
 
95
- if not isinstance(gcs_path, (str | Path | os.PathLike)):
95
+ if isinstance(gcs_path, str):
96
+ gcs_path = _maybe_strip_prefix(gcs_path, file_system)
97
+ else:
98
+ gcs_path = [_maybe_strip_prefix(str(path), file_system) for path in gcs_path]
99
+
96
100
  return _read_geopandas_from_iterable(
97
101
  gcs_path,
98
102
  mask=mask,
@@ -925,3 +929,10 @@ def _get_files_in_subfolders(folderinfo: list[dict]) -> list[tuple]:
925
929
  folderinfo = new_folderinfo
926
930
 
927
931
  return fileinfo
932
+
933
+
934
+ def _maybe_strip_prefix(path, file_system):
935
+ """Strip gcs prefix only if file_system is GCS."""
936
+ if isinstance(file_system, GCSFileSystem) and path.startswith("gs://"):
937
+ return path.replace("gs://", "")
938
+ return path
sgis/maps/examine.py CHANGED
@@ -121,10 +121,8 @@ class Examine:
121
121
  )
122
122
 
123
123
  if sort_values is not None:
124
- if (
125
- sort_values == "area"
126
- or not isinstance(sort_values, str)
127
- and "area" in sort_values
124
+ if sort_values == "area" or (
125
+ not isinstance(sort_values, str) and "area" in sort_values
128
126
  ):
129
127
  self.mask_gdf["area"] = self.mask_gdf.area
130
128
  self.mask_gdf = self.mask_gdf.sort_values(sort_values)
sgis/maps/legend.py CHANGED
@@ -523,7 +523,7 @@ class ContinousLegend(Legend):
523
523
  def __init__(
524
524
  self,
525
525
  labels: list[str] | None = None,
526
- pretty_labels: bool = True,
526
+ pretty_labels: bool = False,
527
527
  label_suffix: str | None = None,
528
528
  label_sep: str = "-",
529
529
  rounding: int | None = None,
sgis/maps/map.py CHANGED
@@ -543,8 +543,10 @@ class Map:
543
543
  def is_maybe_km2():
544
544
  if "area" in self._column and (
545
545
  "km2" in self._column
546
- or "kilomet" in self._column
547
- and ("sq" in self._column or "2" in self._column)
546
+ or (
547
+ "kilomet" in self._column
548
+ and ("sq" in self._column or "2" in self._column)
549
+ )
548
550
  ):
549
551
  return True
550
552
  else:
@@ -209,15 +209,15 @@ class NetworkAnalysisRules:
209
209
  return True
210
210
 
211
211
  def _validate_weight(self, gdf: GeoDataFrame) -> GeoDataFrame:
212
- if "meter" in self.weight or "metre" in self.weight and unit_is_meters(gdf):
212
+ if "meter" in self.weight or ("metre" in self.weight and unit_is_meters(gdf)):
213
213
  if self.nodedist_kmh:
214
214
  raise ValueError("Cannot set 'nodedist_kmh' when 'weight' is meters.")
215
215
  gdf[self.weight] = gdf.length
216
216
  return gdf
217
217
 
218
218
  # allow abbreviation of 'minutes' to be nice
219
- elif (
220
- self.weight == "min" or "minut" in self.weight and "minutes" in gdf.columns
219
+ elif self.weight == "min" or (
220
+ "minut" in self.weight and "minutes" in gdf.columns
221
221
  ):
222
222
  if self.nodedist_multiplier:
223
223
  raise ValueError(
@@ -629,6 +629,8 @@ class _ImageBase:
629
629
  for key, value in self.__dict__.items():
630
630
  if key.startswith("_"):
631
631
  continue
632
+ if key == "file_system" and type(value) is type(getattr(other, key)):
633
+ continue
632
634
  if value != getattr(other, key):
633
635
  print(key, value, getattr(other, key))
634
636
  return False
@@ -747,9 +749,8 @@ class _ImageBandBase(_ImageBase):
747
749
  continue
748
750
  if results is not None:
749
751
  break
750
- elif (
751
- isinstance(value, str)
752
- or hasattr(value, "__iter__")
752
+ elif isinstance(value, str) or (
753
+ hasattr(value, "__iter__")
753
754
  and all(isinstance(x, str | re.Pattern) for x in value)
754
755
  ):
755
756
  try:
@@ -1538,9 +1539,8 @@ class Image(_ImageBandBase):
1538
1539
  else:
1539
1540
  self._all_file_paths = None
1540
1541
 
1541
- if (
1542
- self.metadata is None
1543
- or not len(self.metadata)
1542
+ if self.metadata is None or (
1543
+ not len(self.metadata)
1544
1544
  and "metadata.json" in {Path(x).name for x in self._all_file_paths}
1545
1545
  ):
1546
1546
  with _open_func(
@@ -1845,7 +1845,8 @@ class Image(_ImageBandBase):
1845
1845
  if (
1846
1846
  self.filename_patterns
1847
1847
  and any(_get_non_optional_groups(pat) for pat in self.filename_patterns)
1848
- or self.image_patterns
1848
+ ) or (
1849
+ self.image_patterns
1849
1850
  and any(_get_non_optional_groups(pat) for pat in self.image_patterns)
1850
1851
  ):
1851
1852
  self._bands = [band for band in self._bands if band.band_id is not None]
@@ -1882,8 +1883,7 @@ class Image(_ImageBandBase):
1882
1883
  for group in sort_groups
1883
1884
  for pat in self.filename_patterns
1884
1885
  )
1885
- or all(band.band_id is not None for band in self)
1886
- )
1886
+ ) or all(band.band_id is not None for band in self)
1887
1887
 
1888
1888
  @property
1889
1889
  def tile(self) -> str:
@@ -2846,17 +2846,21 @@ class ImageCollection(_ImageBase):
2846
2846
  """True if the ImageCollection has regexes that should make it sortable by date."""
2847
2847
  sort_group = "date"
2848
2848
  return (
2849
- self.filename_patterns
2850
- and any(
2851
- sort_group in pat.groupindex
2852
- and sort_group in _get_non_optional_groups(pat)
2853
- for pat in self.filename_patterns
2849
+ (
2850
+ self.filename_patterns
2851
+ and any(
2852
+ sort_group in pat.groupindex
2853
+ and sort_group in _get_non_optional_groups(pat)
2854
+ for pat in self.filename_patterns
2855
+ )
2854
2856
  )
2855
- or self.image_patterns
2856
- and any(
2857
- sort_group in pat.groupindex
2858
- and sort_group in _get_non_optional_groups(pat)
2859
- for pat in self.image_patterns
2857
+ or (
2858
+ self.image_patterns
2859
+ and any(
2860
+ sort_group in pat.groupindex
2861
+ and sort_group in _get_non_optional_groups(pat)
2862
+ for pat in self.image_patterns
2863
+ )
2860
2864
  )
2861
2865
  or all(getattr(img, sort_group) is not None for img in self)
2862
2866
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ssb-sgis
3
- Version: 1.2.14
3
+ Version: 1.2.16
4
4
  Summary: GIS functions used at Statistics Norway.
5
5
  Home-page: https://github.com/statisticsnorway/ssb-sgis
6
6
  License: MIT
@@ -17,9 +17,9 @@ Classifier: Topic :: Scientific/Engineering :: GIS
17
17
  Provides-Extra: all
18
18
  Provides-Extra: bucket
19
19
  Provides-Extra: test
20
- Provides-Extra: torch
21
20
  Provides-Extra: xarray
22
21
  Requires-Dist: affine (>=2.4.0)
22
+ Requires-Dist: black (>=25.1.0,<26.0.0)
23
23
  Requires-Dist: branca (>=0.6.0)
24
24
  Requires-Dist: dapla-toolbelt (>=3.0.1) ; extra == "all" or extra == "bucket"
25
25
  Requires-Dist: dask (>=2024.1.1) ; extra == "all" or extra == "test"
@@ -35,17 +35,16 @@ Requires-Dist: mapclassify (>=2.5.0)
35
35
  Requires-Dist: matplotlib (>=3.7.0)
36
36
  Requires-Dist: networkx (>=3.0)
37
37
  Requires-Dist: numpy (>=1.26.4)
38
- Requires-Dist: pandas (>=2.2.1)
38
+ Requires-Dist: pandas (>=2.0.1)
39
39
  Requires-Dist: pyarrow (>=11.0.0)
40
40
  Requires-Dist: pyproj (>=3.6.1)
41
41
  Requires-Dist: rasterio (>=1.3.8)
42
42
  Requires-Dist: requests (>=2.28.2)
43
43
  Requires-Dist: rioxarray (>=0.15.5) ; extra == "all" or extra == "xarray" or extra == "test"
44
44
  Requires-Dist: rtree (>=1.0.1)
45
+ Requires-Dist: ruff (>=0.12.8,<0.13.0)
45
46
  Requires-Dist: scikit-learn (>=1.2.1)
46
47
  Requires-Dist: shapely (>=2.0.1)
47
- Requires-Dist: torch (>=2.4.0) ; extra == "all" or extra == "torch" or extra == "test"
48
- Requires-Dist: torchgeo (>=0.5.2) ; extra == "all" or extra == "torch" or extra == "test"
49
48
  Requires-Dist: typing-extensions (>=4.11.0)
50
49
  Requires-Dist: xarray (>=2024.3.0) ; extra == "all" or extra == "xarray" or extra == "test"
51
50
  Requires-Dist: xyzservices (>=2023.2.0)
@@ -98,7 +97,7 @@ pip install ssb-sgis
98
97
 
99
98
  The sgis package has the following optional dependencies:
100
99
 
101
- - bucket: For working with files stored in GCP buckets
100
+ - bucket: For working with files stored in GCS buckets
102
101
  - torch: Use functionality from PyTorch and torchgeo
103
102
  - xarray: Use functionality from xarray and rioxarray
104
103
  - test: Packages needed for running pytest
@@ -182,9 +181,13 @@ weights["weight"] = 10
182
181
  frequencies = nwa.get_route_frequencies(origins, destinations, weight_df=weights)
183
182
 
184
183
  # plot the results
185
- m = sg.ThematicMap(sg.buff(frequencies, 15), column="frequency", black=True)
186
- m.cmap = "plasma"
187
- m.title = "Number of times each road was used,\nweighted * 10"
184
+ m = sg.ThematicMap(
185
+ sg.buff(frequencies, 15),
186
+ column="frequency",
187
+ black=True,
188
+ cmap="plasma",
189
+ title="Number of times each road was used,\nweighted * 10",
190
+ )
188
191
  m.plot()
189
192
  ```
190
193
 
@@ -199,9 +202,14 @@ service_areas = nwa.service_area(
199
202
  )
200
203
 
201
204
  # plot the results
202
- m = sg.ThematicMap(service_areas, column="minutes", black=True, size=10)
203
- m.k = 10
204
- m.title = "Roads that can be reached within 1 to 10 minutes"
205
+ m = sg.ThematicMap(
206
+ service_areas,
207
+ column="minutes",
208
+ black=True,
209
+ size=10,
210
+ k=10,
211
+ title="Roads that can be reached within 1 to 10 minutes",
212
+ )
205
213
  m.plot()
206
214
  ```
207
215
 
@@ -214,9 +222,15 @@ routes = nwa.get_k_routes(
214
222
  points.iloc[[0]], points.iloc[[1]], k=4, drop_middle_percent=50
215
223
  )
216
224
 
217
- m = sg.ThematicMap(sg.buff(routes, 15), column="k", black=True)
218
- m.title = "Four fastest routes from A to B"
219
- m.legend.title = "Rank"
225
+ m = sg.ThematicMap(
226
+ sg.buff(routes, 15),
227
+ column="k",
228
+ black=True,
229
+ title="Four fastest routes from A to B",
230
+ legend_kwargs=dict(
231
+ title="Rank",
232
+ ),
233
+ )
220
234
  m.plot()
221
235
  ```
222
236
 
@@ -7,7 +7,7 @@ sgis/geopandas_tools/bounds.py,sha256=PsA_rPEDIS0CopLtolWCB01UEdxc8gtsNbUqMd5AOL
7
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
- sgis/geopandas_tools/conversion.py,sha256=CrasgWHAnUmLC5tP73ZTDjQ6ahKFHQGqWj86PUif24M,24176
10
+ sgis/geopandas_tools/conversion.py,sha256=iX954YEpobmn_R1Ecx_zDU1RlWq_67pfbzMXtwTH04I,24162
11
11
  sgis/geopandas_tools/duplicates.py,sha256=TDDM4u1n7SIkyJrOfl1Lno92AmUPqtXBHsj1IUKC0hI,14992
12
12
  sgis/geopandas_tools/general.py,sha256=YRpNEdwTHyFdQOdAfbCmYXS7PxoDjXxoagwpteXkYdI,43937
13
13
  sgis/geopandas_tools/geocoding.py,sha256=sZjUW52ULhQWDLmU51C9_itBePkDuWkp8swvYaiYmJk,679
@@ -23,15 +23,15 @@ sgis/geopandas_tools/utils.py,sha256=X0pRvB1tWgV_0BCrRS1HU9LtLGnZCpvVPxyqM9JGb0Y
23
23
  sgis/helpers.py,sha256=4N6vFWQ3TYVzRHNcWY_fNa_GkFuaZB3vtCkkFND-qs0,9628
24
24
  sgis/io/__init__.py,sha256=uyBr20YDqB2bQttrd5q1JuGOvX32A-MSvS7Wmw5f5qg,177
25
25
  sgis/io/_is_dapla.py,sha256=wmfkSe98IrLhUg3dtXZusV6OVC8VlY1kbc5EQDf3P-Q,358
26
- sgis/io/dapla_functions.py,sha256=9NqkL67WdJJHczIWNdChHZp8T5hlXhcYucX7GWN1mCA,31430
26
+ sgis/io/dapla_functions.py,sha256=quq2HkeR0MZSacllDXjVJlthZebT2ATbU6mjsxODOVA,31796
27
27
  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
- sgis/maps/examine.py,sha256=69nPtMChKmso7Yy8X--UoTWJjKmjMF1VHsdLpPKFbA0,9233
30
+ sgis/maps/examine.py,sha256=yfYYxn0C9gH3ygS9MnWfzyY9upjNuGJdPZPXcv4vO_8,9201
31
31
  sgis/maps/explore.py,sha256=ANbhScthhwznLEUDDjRUBmniGmkdF9zftbzp9dYHu-U,48210
32
32
  sgis/maps/httpserver.py,sha256=I7tTn3hFaTCc-E-T_o9v0nXwMGaS2Xqd4MlWbq8k-J4,3014
33
- sgis/maps/legend.py,sha256=6L6KspAoYuQbOcs-0vWzMDEL_9qvmGuRR7VIL1wsBMI,26898
34
- sgis/maps/map.py,sha256=07YK_oHa2z_yw_es06pd-80dV8YTI5mkTyJxyud707Y,30758
33
+ sgis/maps/legend.py,sha256=gTEWCVIZH1cw6ULVVrJqRR4__uOZvrT3xxQ5lhZMVR4,26899
34
+ sgis/maps/map.py,sha256=iGa0o7NlUMErJCYJpVzkpDvuWJc8iDN_-tH2X2WcBlI,30802
35
35
  sgis/maps/maps.py,sha256=fLK5WUlQ2YTm7t-8260lYxCFvpZN6j0Y-bVYCyv8NAY,23249
36
36
  sgis/maps/norge_i_bilder.json,sha256=G9DIN_2vyn-18UF5wUC-koZxFCbiNxMu0BbCJhMFJUk,15050340
37
37
  sgis/maps/thematicmap.py,sha256=ZtV4Hfylr1ST_cPzi11_lFIsTdY3D1o1EZQbPXZLwyM,25187
@@ -48,7 +48,7 @@ sgis/networkanalysis/directednetwork.py,sha256=Mrc2zHip4P5RNxnyffKm-xU832AVQeSHz
48
48
  sgis/networkanalysis/finding_isolated_networks.py,sha256=Wg4ILhm7uS9RLOGcL0WN8uZBMJYjdljJc8L5DU5nIPY,3754
49
49
  sgis/networkanalysis/network.py,sha256=zV9bAbVdTgTohg2o2RFGy2uhOJrd3Ma57hwIAStxMAQ,7847
50
50
  sgis/networkanalysis/networkanalysis.py,sha256=P2kqE1kBxabBnv4h6ort1IiO4W0XlsJn5DrT7IbeG5w,68651
51
- sgis/networkanalysis/networkanalysisrules.py,sha256=9sXigaCzvKhXFwpeVNMtOiIK3_Hzp9yDpFklmEEAPak,12956
51
+ sgis/networkanalysis/networkanalysisrules.py,sha256=na26iZTpnlwwIEEGswoqMH4W1ZOLN2GIvACZbxn8GPw,12958
52
52
  sgis/networkanalysis/nodes.py,sha256=atFSpqz-_uJHMrf6MC0zhrrcWIydRMFZrsaHC2xr1GU,3374
53
53
  sgis/networkanalysis/traveling_salesman.py,sha256=Jjo6bHY4KJ-eK0LycyTy0sWxZjgITs5MBllZ_G9FhTE,5655
54
54
  sgis/parallel/__init__.py,sha256=fw_Fl3IJk1bKzrRBhZIoOpznJqwd09NVHJJFj2ZLeIU,32
@@ -56,12 +56,12 @@ sgis/parallel/parallel.py,sha256=V7O5mEZdfJpcOPrmn2H4bEGtbzA0FggjQ8dGhznjr80,400
56
56
  sgis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
57
  sgis/raster/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
58
  sgis/raster/base.py,sha256=8JdXXDj8CgJQt5WIkkNbpM5U0pYyQrWQY9dszfUaUQ4,7743
59
- sgis/raster/image_collection.py,sha256=H7d9c6f-LsGXBK8oCpWBlgd2zbLxYvfNMYllnbrO_rk,121697
59
+ sgis/raster/image_collection.py,sha256=QGTRfIZAOnNiiTuIJOaQJW-g4TIZKvJUtQKwTan1sv4,121876
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.14.dist-info/LICENSE,sha256=np3IfD5m0ZUofn_kVzDZqliozuiO6wrktw3LRPjyEiI,1073
65
- ssb_sgis-1.2.14.dist-info/METADATA,sha256=Hhvwb5ydmsvVBuINCUdiElVrH2SZaZ-XThmYG_rtGA4,11741
66
- ssb_sgis-1.2.14.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
67
- ssb_sgis-1.2.14.dist-info/RECORD,,
64
+ ssb_sgis-1.2.16.dist-info/LICENSE,sha256=np3IfD5m0ZUofn_kVzDZqliozuiO6wrktw3LRPjyEiI,1073
65
+ ssb_sgis-1.2.16.dist-info/METADATA,sha256=Ajra6_V1SJDyLMH0qio2HNTN5KvJdqYON-DSSG21wZM,11704
66
+ ssb_sgis-1.2.16.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
67
+ ssb_sgis-1.2.16.dist-info/RECORD,,