ssb-sgis 0.2.6__py3-none-any.whl → 0.2.7__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 CHANGED
@@ -46,6 +46,7 @@ from .geopandas_tools.polygon_operations import (
46
46
  )
47
47
  from .geopandas_tools.to_geodataframe import to_gdf
48
48
  from .helpers import get_name
49
+ from .maps.examine import Examine
49
50
  from .maps.explore import Explore
50
51
  from .maps.httpserver import run_html_server
51
52
  from .maps.legend import Legend
@@ -1,4 +1,5 @@
1
1
  """Functions for polygon geometries."""
2
+ import functools
2
3
  import warnings
3
4
 
4
5
  import geopandas as gpd
@@ -8,6 +9,7 @@ import pandas as pd
8
9
  from geopandas import GeoDataFrame, GeoSeries
9
10
  from shapely import (
10
11
  area,
12
+ difference,
11
13
  get_exterior_ring,
12
14
  get_interior_ring,
13
15
  get_num_interior_rings,
@@ -457,21 +459,19 @@ def get_overlapping_polygon_product(gdf: GeoDataFrame | GeoSeries) -> pd.Index:
457
459
  return series
458
460
 
459
461
 
460
- def close_small_holes(
462
+ def close_all_holes(
461
463
  gdf: GeoDataFrame | GeoSeries,
462
- max_area: int | float,
463
464
  *,
465
+ without_islands: bool = True,
464
466
  copy: bool = True,
465
467
  ) -> GeoDataFrame | GeoSeries:
466
- """Closes holes in polygons if the area is less than the given maximum.
468
+ """Closes all holes in polygons.
467
469
 
468
470
  It takes a GeoDataFrame or GeoSeries of polygons and
469
- fills the holes that are smaller than the specified area given in units of
470
- either square meters ('max_m2') or square kilometers ('max_km2').
471
+ returns the outer circle.
471
472
 
472
473
  Args:
473
474
  gdf: GeoDataFrame or GeoSeries of polygons.
474
- max_area: The maximum area in the unit of the GeoDataFrame's crs.
475
475
  copy: if True (default), the input GeoDataFrame or GeoSeries is copied.
476
476
  Defaults to True.
477
477
 
@@ -479,17 +479,11 @@ def close_small_holes(
479
479
  A GeoDataFrame or GeoSeries of polygons with closed holes in the geometry
480
480
  column.
481
481
 
482
- Raises:
483
- ValueError: If the coordinate reference system of the GeoDataFrame is not in
484
- meter units.
485
- ValueError: If both 'max_m2' and 'max_km2' is given.
486
-
487
482
  Examples
488
483
  --------
489
-
490
484
  Let's create a circle with a hole in it.
491
485
 
492
- >>> from sgis import close_small_holes, buff, to_gdf
486
+ >>> from sgis import close_all_holes, buff, to_gdf
493
487
  >>> point = to_gdf([260000, 6650000], crs=25833)
494
488
  >>> point
495
489
  geometry
@@ -501,50 +495,54 @@ def close_small_holes(
501
495
  0 2.355807e+06
502
496
  dtype: float64
503
497
 
504
- Close holes smaller than 1 square kilometer (1 million square meters).
498
+ Close the hole.
505
499
 
506
- >>> holes_closed = close_small_holes(circle_with_hole, max_area=1_000_000)
500
+ >>> holes_closed = close_all_holes(circle_with_hole)
507
501
  >>> holes_closed.area
508
502
  0 3.141076e+06
509
503
  dtype: float64
510
-
511
- The hole will not be closed if it is larger.
512
-
513
- >>> holes_closed = close_small_holes(circle_with_hole, max_area=1_000)
514
- >>> holes_closed.area
515
- 0 2.355807e+06
516
- dtype: float64
517
504
  """
518
- if copy:
519
- gdf = gdf.copy()
520
-
521
- if isinstance(gdf, GeoDataFrame):
522
- gdf["geometry"] = gdf.geometry.map(
523
- lambda x: _close_small_holes_poly(x, max_area)
505
+ if not isinstance(gdf, (GeoDataFrame, GeoSeries)):
506
+ raise ValueError(
507
+ f"'gdf' should be of type GeoDataFrame or GeoSeries. Got {type(gdf)}"
524
508
  )
525
- return gdf
526
509
 
527
- elif isinstance(gdf, gpd.GeoSeries):
528
- return gdf.map(lambda x: _close_small_holes_poly(x, max_area))
510
+ if copy:
511
+ gdf = gdf.copy()
529
512
 
513
+ if without_islands:
514
+ all_geoms = gdf.unary_union
515
+ if isinstance(gdf, GeoDataFrame):
516
+ gdf["geometry"] = gdf.geometry.map(
517
+ lambda x: _close_all_holes_no_islands(x, all_geoms)
518
+ )
519
+ return gdf
520
+ else:
521
+ return gdf.map(lambda x: _close_all_holes_no_islands(x, all_geoms))
530
522
  else:
531
- raise ValueError(
532
- f"'gdf' should be of type GeoDataFrame or GeoSeries. Got {type(gdf)}"
533
- )
523
+ if isinstance(gdf, GeoDataFrame):
524
+ gdf["geometry"] = gdf.geometry.map(_close_all_holes)
525
+ return gdf
526
+ else:
527
+ return gdf.map(_close_all_holes)
534
528
 
535
529
 
536
- def close_all_holes(
530
+ def close_small_holes(
537
531
  gdf: GeoDataFrame | GeoSeries,
532
+ max_area: int | float,
538
533
  *,
534
+ without_islands: bool = True,
539
535
  copy: bool = True,
540
536
  ) -> GeoDataFrame | GeoSeries:
541
- """Closes all holes in polygons.
537
+ """Closes holes in polygons if the area is less than the given maximum.
542
538
 
543
539
  It takes a GeoDataFrame or GeoSeries of polygons and
544
- returns the outer circle.
540
+ fills the holes that are smaller than the specified area given in units of
541
+ either square meters ('max_m2') or square kilometers ('max_km2').
545
542
 
546
543
  Args:
547
544
  gdf: GeoDataFrame or GeoSeries of polygons.
545
+ max_area: The maximum area in the unit of the GeoDataFrame's crs.
548
546
  copy: if True (default), the input GeoDataFrame or GeoSeries is copied.
549
547
  Defaults to True.
550
548
 
@@ -552,11 +550,17 @@ def close_all_holes(
552
550
  A GeoDataFrame or GeoSeries of polygons with closed holes in the geometry
553
551
  column.
554
552
 
553
+ Raises:
554
+ ValueError: If the coordinate reference system of the GeoDataFrame is not in
555
+ meter units.
556
+ ValueError: If both 'max_m2' and 'max_km2' is given.
557
+
555
558
  Examples
556
559
  --------
560
+
557
561
  Let's create a circle with a hole in it.
558
562
 
559
- >>> from sgis import close_all_holes, buff, to_gdf
563
+ >>> from sgis import close_small_holes, buff, to_gdf
560
564
  >>> point = to_gdf([260000, 6650000], crs=25833)
561
565
  >>> point
562
566
  geometry
@@ -568,35 +572,51 @@ def close_all_holes(
568
572
  0 2.355807e+06
569
573
  dtype: float64
570
574
 
571
- Close the hole.
575
+ Close holes smaller than 1 square kilometer (1 million square meters).
572
576
 
573
- >>> holes_closed = close_all_holes(circle_with_hole)
577
+ >>> holes_closed = close_small_holes(circle_with_hole, max_area=1_000_000)
574
578
  >>> holes_closed.area
575
579
  0 3.141076e+06
576
580
  dtype: float64
577
- """
578
- if copy:
579
- gdf = gdf.copy()
580
581
 
581
- def close_all_holes_func(poly):
582
- return unary_union(polygons(get_exterior_ring(get_parts(poly))))
582
+ The hole will not be closed if it is larger.
583
583
 
584
- close_all_holes_func = np.vectorize(close_all_holes_func)
584
+ >>> holes_closed = close_small_holes(circle_with_hole, max_area=1_000)
585
+ >>> holes_closed.area
586
+ 0 2.355807e+06
587
+ dtype: float64
588
+ """
589
+ if not isinstance(gdf, (GeoSeries, GeoDataFrame)):
590
+ raise ValueError(
591
+ f"'gdf' should be of type GeoDataFrame or GeoSeries. Got {type(gdf)}"
592
+ )
585
593
 
586
- if isinstance(gdf, GeoDataFrame):
587
- gdf["geometry"] = close_all_holes_func(gdf.geometry)
588
- return gdf
594
+ if copy:
595
+ gdf = gdf.copy()
589
596
 
590
- elif isinstance(gdf, gpd.GeoSeries):
591
- return close_all_holes_func(gdf)
597
+ if without_islands:
598
+ all_geoms = gdf.unary_union
592
599
 
600
+ if isinstance(gdf, GeoDataFrame):
601
+ gdf["geometry"] = gdf.geometry.map(
602
+ lambda x: _close_small_holes_no_islands(x, max_area, all_geoms)
603
+ )
604
+ return gdf
605
+ else:
606
+ return gdf.map(
607
+ lambda x: _close_small_holes_no_islands(x, max_area, all_geoms)
608
+ )
593
609
  else:
594
- raise ValueError(
595
- f"'gdf' should be of type GeoDataFrame or GeoSeries. Got {type(gdf)}"
596
- )
610
+ if isinstance(gdf, GeoDataFrame):
611
+ gdf["geometry"] = gdf.geometry.map(
612
+ lambda x: _close_small_holes(x, max_area)
613
+ )
614
+ return gdf
615
+ else:
616
+ return gdf.map(lambda x: _close_small_holes(x, max_area))
597
617
 
598
618
 
599
- def _close_small_holes_poly(poly, max_area):
619
+ def _close_small_holes(poly, max_area):
600
620
  """Closes cmall holes within one shapely geometry of polygons."""
601
621
 
602
622
  # start with a list containing the polygon,
@@ -612,7 +632,56 @@ def _close_small_holes_poly(poly, max_area):
612
632
  for n in range(n_interior_rings):
613
633
  hole = polygons(get_interior_ring(part, n))
614
634
 
635
+ print(area(hole))
636
+
615
637
  if area(hole) < max_area:
616
638
  holes_closed.append(hole)
617
639
 
618
640
  return unary_union(holes_closed)
641
+
642
+
643
+ def _close_small_holes_no_islands(poly, max_area, all_geoms):
644
+ """Closes small holes within one shapely geometry of polygons."""
645
+
646
+ # start with a list containing the polygon,
647
+ # then append all holes smaller than 'max_km2' to the list.
648
+ holes_closed = [poly]
649
+ singlepart = get_parts(poly)
650
+ for part in singlepart:
651
+ n_interior_rings = get_num_interior_rings(part)
652
+
653
+ if not (n_interior_rings):
654
+ continue
655
+
656
+ for n in range(n_interior_rings):
657
+ hole = polygons(get_interior_ring(part, n))
658
+ no_islands = unary_union(hole.difference(all_geoms))
659
+ if area(no_islands) < max_area:
660
+ holes_closed.append(no_islands)
661
+
662
+ return unary_union(holes_closed)
663
+
664
+
665
+ def _close_all_holes(poly):
666
+ return unary_union(polygons(get_exterior_ring(get_parts(poly))))
667
+
668
+
669
+ def _close_all_holes_no_islands(poly, all_geoms):
670
+ """Closes all holes within one shapely geometry of polygons."""
671
+
672
+ # start with a list containing the polygon,
673
+ # then append all holes smaller than 'max_km2' to the list.
674
+ holes_closed = [poly]
675
+ singlepart = get_parts(poly)
676
+ for part in singlepart:
677
+ n_interior_rings = get_num_interior_rings(part)
678
+
679
+ if not (n_interior_rings):
680
+ continue
681
+
682
+ for n in range(n_interior_rings):
683
+ hole = polygons(get_interior_ring(part, n))
684
+ no_islands = unary_union(hole.difference(all_geoms))
685
+ holes_closed.append(no_islands)
686
+
687
+ return unary_union(holes_closed)
@@ -5,7 +5,7 @@ import geopandas as gpd
5
5
  import pandas as pd
6
6
  from geopandas import GeoDataFrame, GeoSeries
7
7
  from pandas.api.types import is_array_like, is_dict_like, is_list_like
8
- from shapely import Geometry, wkb, wkt
8
+ from shapely import Geometry, box, wkb, wkt
9
9
  from shapely.geometry import Point
10
10
  from shapely.ops import unary_union
11
11
 
@@ -168,6 +168,8 @@ def to_gdf(
168
168
  geoseries = GeoSeries(
169
169
  _make_shapely_geoms(list(geom.values())[0]), index=index
170
170
  )
171
+ elif isinstance(geom, pd.Series):
172
+ geoseries = GeoSeries(_make_shapely_geoms(geom), index=index)
171
173
  else:
172
174
  geoseries = GeoSeries(_make_shapely_geoms(geom.iloc[:, 0]), index=index)
173
175
  return GeoDataFrame({key: geoseries}, geometry=key, crs=crs, **kwargs)
@@ -292,9 +294,11 @@ def _make_one_shapely_geom(geom):
292
294
  elif len(geom) == 2 or len(geom) == 3:
293
295
  return Point(geom)
294
296
 
297
+ elif len(geom) == 4:
298
+ return box(*geom)
295
299
  else:
296
300
  raise ValueError(
297
301
  "If 'geom' is an iterable, each item should consist of "
298
- "wkt, wkb or 2/3 coordinates (x, y, z). Got ",
302
+ "wkt, wkb or (x, y (z) or bbox). Got ",
299
303
  geom,
300
304
  )
sgis/maps/examine.py ADDED
@@ -0,0 +1,192 @@
1
+ import geopandas as gpd
2
+
3
+ from ..helpers import unit_is_degrees
4
+ from .maps import clipmap
5
+
6
+
7
+ class Examine:
8
+ """Explore geometries one row at a time.
9
+
10
+ It takes one or more GeoDataFrames and shows an interactive map
11
+ of one area at the time with the 'next', 'prev' and 'current' methods.
12
+
13
+ After creating the examiner object, the 'next' method will create a map
14
+ showing all geometries within a given radius (the size parameter) of the
15
+ first geometry in 'mask_gdf' (or the first speficied gdf). The 'next' method
16
+ can then be repeated.
17
+
18
+ Args:
19
+ *gdfs: One or more GeoDataFrames. The rows of the first GeoDataFrame
20
+ will be used as masks, unless 'mask_gdf' is specified.
21
+ column: Column to use as colors.
22
+ mask_gdf: Optional GeoDataFrame to use as mask iterator. The geometries
23
+ of mask_gdf will not be shown.
24
+ size: Number of meters (or other crs unit) to buffer the mask geometry
25
+ before clipping.
26
+ sort_values: Optional sorting column(s) of the mask GeoDataFrame. Rows
27
+ will be iterated through from the top.
28
+ **kwargs: Additional keyword arguments passed to sgis.clipmap.
29
+
30
+ Examples
31
+ --------
32
+ Create the examiner.
33
+
34
+ >>> import sgis as sg
35
+ >>> roads = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/roads_oslo_2022.parquet")
36
+ >>> points = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/points_oslo.parquet")
37
+ >>> e = sg.Examine(points, roads)
38
+ >>> e
39
+
40
+ Then the line below can be repeated for all rows if 'points'. This has to be
41
+ in a separate notebook cell to the previous.
42
+
43
+ >>> e.next()
44
+
45
+ Previous geometry:
46
+
47
+ >>> e.prev()
48
+
49
+ Repeating the current area with another layer and new column:
50
+
51
+ >>> some_points = points.sample(100)
52
+ >>> e.current(some_points, column="idx")
53
+
54
+ The row number can also be specified manually.
55
+ Can be done in 'next', 'prev' and 'current'.
56
+
57
+ >>> e.next(i=101)
58
+
59
+ This will create an examiner where 'points' is not shown, only used as mask.
60
+
61
+ >>> e = sg.Examine(roads, mask_gdf=points, column="oneway")
62
+ """
63
+
64
+ def __init__(
65
+ self,
66
+ *gdfs: gpd.GeoDataFrame,
67
+ column: str | None = None,
68
+ mask_gdf: gpd.GeoDataFrame | None = None,
69
+ sort_values: str | None = None,
70
+ size: int | float = 1000,
71
+ **kwargs,
72
+ ):
73
+ if not all(isinstance(gdf, gpd.GeoDataFrame) for gdf in gdfs):
74
+ raise ValueError("gdfs must be of type GeoDataFrame.")
75
+
76
+ self.gdfs = gdfs
77
+ if mask_gdf is None:
78
+ self.mask_gdf = gdfs[0]
79
+ else:
80
+ self.mask_gdf = mask_gdf
81
+
82
+ if unit_is_degrees(self.mask_gdf) and size > 360:
83
+ raise ValueError(
84
+ "CRS unit is degrees. Use geopandas' "
85
+ "to_crs method to change crs to e.g. UTM. "
86
+ "Or set 'size' to a smaller number."
87
+ )
88
+
89
+ if sort_values is not None:
90
+ self.mask_gdf = self.mask_gdf.sort_values(sort_values)
91
+
92
+ self.indices = list(range(len(gdfs[0])))
93
+ self.i = 0
94
+ self.column = column
95
+ self.size = size
96
+ self.kwargs = kwargs
97
+
98
+ def next(self, *gdfs, i: int | None = None, **kwargs):
99
+ """Displays a map of geometries within the next row of the mask gdf.
100
+
101
+ Args:
102
+ *gdfs: Optional GeoDataFrames to be added on top of the current.
103
+ i: Optionally set the integer index of which row to use as mask.
104
+ **kwargs: Additional keyword arguments passed to sgis.clipmap.
105
+ """
106
+ gdfs = () if not gdfs else gdfs
107
+ self.gdfs = self.gdfs + gdfs
108
+ if kwargs:
109
+ kwargs = self._fix_kwargs(kwargs)
110
+ self.kwargs = self.kwargs | kwargs
111
+
112
+ if i:
113
+ self.i = i
114
+
115
+ if self.i >= len(self.mask_gdf):
116
+ print("All rows are shown.")
117
+ return
118
+
119
+ print(f"{self.i + 1} of {len(self.mask_gdf)}")
120
+ clipmap(
121
+ *self.gdfs,
122
+ self.column,
123
+ mask=self.mask_gdf.iloc[[self.i]].buffer(self.size),
124
+ **self.kwargs,
125
+ )
126
+ self.i += 1
127
+
128
+ def prev(self, *gdfs, i: int | None = None, **kwargs):
129
+ """Displays a map of geometries within the previus row of the mask gdf.
130
+
131
+ Args:
132
+ *gdfs: Optional GeoDataFrames to be added on top of the current.
133
+ i: Optionally set the integer index of which row to use as mask.
134
+ **kwargs: Additional keyword arguments passed to sgis.clipmap.
135
+ """
136
+ gdfs = () if not gdfs else gdfs
137
+ self.gdfs = self.gdfs + gdfs
138
+ if kwargs:
139
+ kwargs = self._fix_kwargs(kwargs)
140
+ self.kwargs = self.kwargs | kwargs
141
+
142
+ self.i -= 2
143
+
144
+ if i:
145
+ self.i = i
146
+
147
+ print(f"{self.i + 1} of {len(self.mask_gdf)}")
148
+ clipmap(
149
+ *self.gdfs,
150
+ self.column,
151
+ mask=self.mask_gdf.iloc[[self.i]].buffer(self.size),
152
+ **self.kwargs,
153
+ )
154
+
155
+ def current(self, *gdfs, i: int | None = None, **kwargs):
156
+ """Repeat the last shown map."""
157
+ gdfs = () if not gdfs else gdfs
158
+ self.gdfs = self.gdfs + gdfs
159
+ if kwargs:
160
+ kwargs = self._fix_kwargs(kwargs)
161
+ self.kwargs = self.kwargs | kwargs
162
+
163
+ if i:
164
+ self.i = i
165
+
166
+ print(f"{self.i + 1} of {len(self.mask_gdf)}")
167
+ clipmap(
168
+ *self.gdfs,
169
+ self.column,
170
+ mask=self.mask_gdf.iloc[[self.i]].buffer(self.size),
171
+ **self.kwargs,
172
+ )
173
+
174
+ def get_current_mask(self) -> gpd.GeoDataFrame:
175
+ """Returns a GeoDataFrame of the last shown mask geometry."""
176
+ return self.mask_gdf.iloc[[self.i]]
177
+
178
+ def get_current_geoms(self) -> tuple[gpd.GeoDataFrame]:
179
+ """Returns all GeoDataFrames in the area of the last shown mask geometry."""
180
+ mask = self.mask_gdf.iloc[[self.i]]
181
+ gdfs = ()
182
+ for gdf in self.gdfs:
183
+ gdfs = gdfs + (gdf.clip(mask.buffer(self.size)),)
184
+ return gdfs
185
+
186
+ def _fix_kwargs(self, kwargs) -> dict:
187
+ self.size = kwargs.pop("size", self.size)
188
+ self.column = kwargs.pop("column", self.column)
189
+ return kwargs
190
+
191
+ def __repr__(self) -> str:
192
+ return f"{self.__class__}(indices={len(self.indices)}, current={self.i}, n_gdfs={len(self.gdfs)})"
sgis/maps/map.py CHANGED
@@ -467,6 +467,8 @@ class Map:
467
467
  if gdf[self._column].isna().all():
468
468
  return np.repeat(len(bins), len(gdf))
469
469
 
470
+ # need numpy.nan instead of pd.NA as of now
471
+ gdf[self._column] = gdf[self._column].fillna(np.nan)
470
472
  classified = np.searchsorted(bins, gdf[self._column])
471
473
 
472
474
  return classified
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ssb-sgis
3
- Version: 0.2.6
3
+ Version: 0.2.7
4
4
  Summary: GIS functions used at Statistics Norway.
5
5
  Home-page: https://github.com/statisticsnorway/ssb-sgis
6
6
  License: MIT
@@ -1,4 +1,4 @@
1
- sgis/__init__.py,sha256=7XYr7wiJ4lw4lQDSj7B2JhLzREA_sgw3_CuqWaJf9b8,2334
1
+ sgis/__init__.py,sha256=BWIQpUVt_X9jFJ6VkJO1XVcGQiOKv60PskNG5XO26G0,2368
2
2
  sgis/dapla.py,sha256=BlJ62kLwpTTQtmbj0Yutbh-bwokVPXHVb3QsRlMugF8,3542
3
3
  sgis/exceptions.py,sha256=ztMp4sB9xxPvwj2IEsO5kOaB4FmHuU_7-M2pZ7qaxTs,576
4
4
  sgis/geopandas_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -8,14 +8,15 @@ sgis/geopandas_tools/geometry_types.py,sha256=o3MbBP-aI7hVWWKVr_5p91TDhjiqZ_2IGx
8
8
  sgis/geopandas_tools/neighbors.py,sha256=tv8bmYgq4VNFbXmT2wcmJsFH8946NwbIBMQXAi3n8L4,14520
9
9
  sgis/geopandas_tools/overlay.py,sha256=RSxrDF0sXs6ZMxbeBJC9HFBVM4yaz10-cdbq3SCosFQ,11862
10
10
  sgis/geopandas_tools/point_operations.py,sha256=3JynroucouAbpON4DWG32S3MQQGmfIJuY7D6gkqtk70,6888
11
- sgis/geopandas_tools/polygon_operations.py,sha256=PfdrYLMmPtmlvOc9TkwYabsXxGe8B25F_Vzc7Sp1WUM,20336
12
- sgis/geopandas_tools/to_geodataframe.py,sha256=4jOy0YvXBIiOEqQx7_ept5xfd39R1XKPN_OVK8kxhp8,9722
11
+ sgis/geopandas_tools/polygon_operations.py,sha256=ZzRx57w4LodN8_P_Tqc-zBAxGCvgvObIi9kJQKa-LLc,22646
12
+ sgis/geopandas_tools/to_geodataframe.py,sha256=g1NqPVVH6hAdMupWxHVd10EvipLY9wPiahh2u_vLOnk,9887
13
13
  sgis/helpers.py,sha256=OqTojkSl-JVKlJzqqB-d_0CH6mk7_LS1DkiIjp1gD8E,2674
14
14
  sgis/maps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ sgis/maps/examine.py,sha256=Wf48WwyNyPC1vYdw-n7GpvJYhwd-YMd_VZLOUI5vWZ4,6479
15
16
  sgis/maps/explore.py,sha256=mab8LE8c_dsGwS1gVCCA2A3r5_Vh7hnzEfEs5MBadvE,23631
16
17
  sgis/maps/httpserver.py,sha256=7ksCSs-WlchcREgjdCZd6II-riJpox34HpVXsCzN_AU,1923
17
18
  sgis/maps/legend.py,sha256=GXAqGOb_zAWcDavd5aHzRyRB7nTRhPCQfSupYA693lk,20499
18
- sgis/maps/map.py,sha256=9sqidnL_ERS0gkmXoEnOS-mAkqsT1kId_X2J2KG5tDU,18490
19
+ sgis/maps/map.py,sha256=niK6N0eFJjAalxjHTNA7kh-2KuazLVsnWlu8i9Ava7o,18611
19
20
  sgis/maps/maps.py,sha256=NaK_wu4RGf6kKRUnnY7gLtxAY9x0d6gKxgQLubDbgHY,15961
20
21
  sgis/maps/thematicmap.py,sha256=6aVPciftW1YjxjRVQDipxayl3aI3tHpYiZ3HfpnSavc,14132
21
22
  sgis/networkanalysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -33,7 +34,7 @@ sgis/networkanalysis/networkanalysisrules.py,sha256=BhhaSXIyBRNzxSOUP2kVBIR--TRq
33
34
  sgis/networkanalysis/nodes.py,sha256=Ys3FjB39Pir3U0jOoLKIPxCC4psC9mdlqdC7G6dSJg0,6767
34
35
  sgis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
36
  sgis/read_parquet.py,sha256=GSW2NDy4-XosbamPEzB1xhWxFAPHuGEJZglfQ-V6DzY,3774
36
- ssb_sgis-0.2.6.dist-info/LICENSE,sha256=lL2h0dNKGTKAE0CjTy62SDbRennVD1xPgM5LzGqhKeo,1074
37
- ssb_sgis-0.2.6.dist-info/METADATA,sha256=elNsqzxjoSHPYPuH4fBF1Ims1Qb_qm0a4nxACdH_q7g,8831
38
- ssb_sgis-0.2.6.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
39
- ssb_sgis-0.2.6.dist-info/RECORD,,
37
+ ssb_sgis-0.2.7.dist-info/LICENSE,sha256=lL2h0dNKGTKAE0CjTy62SDbRennVD1xPgM5LzGqhKeo,1074
38
+ ssb_sgis-0.2.7.dist-info/METADATA,sha256=hpcq2ydyXosFFnw-35qJtrdL3a7bhdblNERuDUiQea8,8831
39
+ ssb_sgis-0.2.7.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
40
+ ssb_sgis-0.2.7.dist-info/RECORD,,