ssb-sgis 1.1.12__tar.gz → 1.1.14__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.
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/PKG-INFO +1 -1
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/pyproject.toml +1 -1
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/polygon_operations.py +0 -6
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/io/dapla_functions.py +26 -15
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/maps/explore.py +1 -1
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/maps/map.py +2 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/raster/image_collection.py +83 -12
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/LICENSE +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/README.md +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/__init__.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/conf.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/debug_config.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/exceptions.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/__init__.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/bounds.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/buffer_dissolve_explode.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/centerlines.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/cleaning.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/conversion.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/duplicates.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/general.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/geocoding.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/geometry_types.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/neighbors.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/overlay.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/point_operations.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/polygons_as_rings.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/geopandas_tools/sfilter.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/helpers.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/io/__init__.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/io/_is_dapla.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/io/opener.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/io/read_parquet.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/maps/__init__.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/maps/examine.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/maps/httpserver.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/maps/legend.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/maps/maps.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/maps/norge_i_bilder.json +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/maps/thematicmap.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/maps/tilesources.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/maps/wms.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/__init__.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/_get_route.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/_od_cost_matrix.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/_points.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/_service_area.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/closing_network_holes.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/cutting_lines.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/directednetwork.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/finding_isolated_networks.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/network.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/networkanalysis.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/networkanalysisrules.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/nodes.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/networkanalysis/traveling_salesman.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/parallel/__init__.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/parallel/parallel.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/py.typed +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/raster/__init__.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/raster/base.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/raster/indices.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/raster/regex.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/raster/sentinel_config.py +0 -0
- {ssb_sgis-1.1.12 → ssb_sgis-1.1.14}/src/sgis/raster/zonal.py +0 -0
|
@@ -425,12 +425,6 @@ def eliminate_by_longest(
|
|
|
425
425
|
explore_locals(center=_DEBUG_CONFIG["center"])
|
|
426
426
|
|
|
427
427
|
if not _recurse and len(isolated):
|
|
428
|
-
if 0:
|
|
429
|
-
isolated.geometry = isolated.buffer(
|
|
430
|
-
-PRECISION,
|
|
431
|
-
resolution=1,
|
|
432
|
-
join_style=2,
|
|
433
|
-
)
|
|
434
428
|
out, isolated = _recursively_eliminate_new_neighbors(
|
|
435
429
|
out,
|
|
436
430
|
isolated,
|
|
@@ -109,7 +109,7 @@ def read_geopandas(
|
|
|
109
109
|
if single_eq_filter:
|
|
110
110
|
try:
|
|
111
111
|
expression = "".join(next(iter(filters))).replace("==", "=")
|
|
112
|
-
glob_func =
|
|
112
|
+
glob_func = _get_glob_func(file_system)
|
|
113
113
|
paths = glob_func(str(Path(gcs_path) / expression))
|
|
114
114
|
if paths:
|
|
115
115
|
return _read_geopandas_from_iterable(
|
|
@@ -543,7 +543,7 @@ def _write_partitioned_geoparquet(
|
|
|
543
543
|
if df[col].isna().all() and not kwargs.get("schema"):
|
|
544
544
|
raise ValueError("Must specify 'schema' when all rows are NA.")
|
|
545
545
|
|
|
546
|
-
glob_func =
|
|
546
|
+
glob_func = _get_glob_func(file_system)
|
|
547
547
|
|
|
548
548
|
if file_system.exists(path) and file_system.isfile(path):
|
|
549
549
|
_remove_file(path, file_system)
|
|
@@ -596,7 +596,7 @@ def _write_partitioned_geoparquet(
|
|
|
596
596
|
executor.map(threaded_write, dfs, paths)
|
|
597
597
|
|
|
598
598
|
|
|
599
|
-
def
|
|
599
|
+
def _get_glob_func(file_system) -> functools.partial:
|
|
600
600
|
try:
|
|
601
601
|
return functools.partial(file_system.glob)
|
|
602
602
|
except AttributeError:
|
|
@@ -724,9 +724,9 @@ def _read_partitioned_parquet(
|
|
|
724
724
|
**kwargs,
|
|
725
725
|
):
|
|
726
726
|
file_system = _get_file_system(file_system, kwargs)
|
|
727
|
+
glob_func = _get_glob_func(file_system)
|
|
727
728
|
|
|
728
729
|
if child_paths is None:
|
|
729
|
-
glob_func = _get_glob(file_system)
|
|
730
730
|
child_paths = list(glob_func(str(Path(path) / "**/*.parquet")))
|
|
731
731
|
|
|
732
732
|
filters = _filters_to_expression(filters)
|
|
@@ -735,18 +735,29 @@ def _read_partitioned_parquet(
|
|
|
735
735
|
bbox, _ = _get_bounds_parquet_from_open_file(file, file_system)
|
|
736
736
|
return shapely.box(*bbox).intersects(to_shapely(mask))
|
|
737
737
|
|
|
738
|
-
def read(
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
738
|
+
def read(child_path: str) -> pyarrow.Table | None:
|
|
739
|
+
try:
|
|
740
|
+
with file_system.open(child_path, "rb") as file:
|
|
741
|
+
if mask is not None and not intersects(file, mask):
|
|
742
|
+
return
|
|
742
743
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
744
|
+
# 'get' instead of 'pop' because dict is mutable
|
|
745
|
+
schema = kwargs.get("schema", pq.read_schema(file))
|
|
746
|
+
new_kwargs = {
|
|
747
|
+
key: value for key, value in kwargs.items() if key != "schema"
|
|
748
|
+
}
|
|
748
749
|
|
|
749
|
-
|
|
750
|
+
return read_func(file, schema=schema, filters=filters, **new_kwargs)
|
|
751
|
+
except ArrowInvalid as e:
|
|
752
|
+
if not len(
|
|
753
|
+
{
|
|
754
|
+
x
|
|
755
|
+
for x in glob_func(str(Path(child_path) / "**"))
|
|
756
|
+
if not paths_are_equal(child_path, x)
|
|
757
|
+
}
|
|
758
|
+
):
|
|
759
|
+
raise e
|
|
760
|
+
# allow not being able to read hard-to-delete empty directories
|
|
750
761
|
|
|
751
762
|
with ThreadPoolExecutor() as executor:
|
|
752
763
|
results = [
|
|
@@ -790,7 +801,7 @@ def paths_are_equal(path1: Path | str, path2: Path | str) -> bool:
|
|
|
790
801
|
|
|
791
802
|
|
|
792
803
|
def get_child_paths(path, file_system) -> list[str]:
|
|
793
|
-
glob_func =
|
|
804
|
+
glob_func = _get_glob_func(file_system)
|
|
794
805
|
return [
|
|
795
806
|
x
|
|
796
807
|
for x in glob_func(str(Path(path) / "**/*.parquet"))
|
|
@@ -729,6 +729,8 @@ class Map:
|
|
|
729
729
|
"""Place the column values into groups."""
|
|
730
730
|
bins = bins.copy()
|
|
731
731
|
|
|
732
|
+
assert gdf.index.is_unique
|
|
733
|
+
|
|
732
734
|
# if equal lenght, convert to integer and check for equality
|
|
733
735
|
if len(bins) == len(self._unique_values):
|
|
734
736
|
if gdf[self._column].isna().all():
|
|
@@ -2,6 +2,7 @@ import datetime
|
|
|
2
2
|
import functools
|
|
3
3
|
import glob
|
|
4
4
|
import itertools
|
|
5
|
+
import json
|
|
5
6
|
import os
|
|
6
7
|
import random
|
|
7
8
|
import re
|
|
@@ -468,8 +469,8 @@ class _ImageBase:
|
|
|
468
469
|
regexes = (regexes,)
|
|
469
470
|
return tuple(re.compile(regexes, flags=re.VERBOSE) for regexes in regexes)
|
|
470
471
|
|
|
471
|
-
@staticmethod
|
|
472
472
|
def _metadata_to_nested_dict(
|
|
473
|
+
self,
|
|
473
474
|
metadata: str | Path | os.PathLike | dict | pd.DataFrame | None,
|
|
474
475
|
) -> dict[str, dict[str, Any]]:
|
|
475
476
|
"""Construct metadata dict from dictlike, DataFrame or file path.
|
|
@@ -932,14 +933,20 @@ class Band(_ImageBandBase):
|
|
|
932
933
|
}
|
|
933
934
|
|
|
934
935
|
if self.metadata:
|
|
936
|
+
parent = _fix_path(str(Path(self.path).parent))
|
|
935
937
|
if self.path is not None:
|
|
936
938
|
self.metadata = {
|
|
937
|
-
key: value
|
|
938
|
-
for key, value in self.metadata.items()
|
|
939
|
-
if key == self.path
|
|
939
|
+
key: value for key, value in self.metadata.items() if key == parent
|
|
940
940
|
}
|
|
941
|
-
|
|
942
|
-
|
|
941
|
+
for key, value in self.metadata.get(parent, {}).items():
|
|
942
|
+
if key == "bands" and self.band_id in value:
|
|
943
|
+
band_metadata = value[self.band_id]
|
|
944
|
+
for band_key, band_value in band_metadata.items():
|
|
945
|
+
if band_key in dir(self):
|
|
946
|
+
setattr(self, f"_{band_key}", band_value)
|
|
947
|
+
else:
|
|
948
|
+
setattr(self, band_key, band_value)
|
|
949
|
+
continue
|
|
943
950
|
if key in dir(self):
|
|
944
951
|
setattr(self, f"_{key}", value)
|
|
945
952
|
else:
|
|
@@ -1592,6 +1599,22 @@ class Image(_ImageBandBase):
|
|
|
1592
1599
|
else:
|
|
1593
1600
|
self._all_file_paths = None
|
|
1594
1601
|
|
|
1602
|
+
if not self.metadata and "metadata.json" in {
|
|
1603
|
+
Path(x).name for x in self._all_file_paths
|
|
1604
|
+
}:
|
|
1605
|
+
with _open_func(
|
|
1606
|
+
next(
|
|
1607
|
+
iter(
|
|
1608
|
+
{
|
|
1609
|
+
x
|
|
1610
|
+
for x in self._all_file_paths
|
|
1611
|
+
if str(x).endswith("metadata.json")
|
|
1612
|
+
}
|
|
1613
|
+
)
|
|
1614
|
+
)
|
|
1615
|
+
) as file:
|
|
1616
|
+
self.metadata = json.load(file)
|
|
1617
|
+
|
|
1595
1618
|
if df is None:
|
|
1596
1619
|
if not self._all_file_paths:
|
|
1597
1620
|
self._all_file_paths = {self.path}
|
|
@@ -1616,12 +1639,10 @@ class Image(_ImageBandBase):
|
|
|
1616
1639
|
key: value for key, value in self.metadata.items() if self.path in key
|
|
1617
1640
|
}
|
|
1618
1641
|
|
|
1619
|
-
if self.metadata:
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
metadata = {}
|
|
1624
|
-
for key, value in metadata.items():
|
|
1642
|
+
if self.metadata.get(self.path, {}):
|
|
1643
|
+
for key, value in self.metadata[self.path].items():
|
|
1644
|
+
if key in {"bands"}:
|
|
1645
|
+
continue
|
|
1625
1646
|
if key in dir(self):
|
|
1626
1647
|
setattr(self, f"_{key}", value)
|
|
1627
1648
|
else:
|
|
@@ -1705,6 +1726,56 @@ class Image(_ImageBandBase):
|
|
|
1705
1726
|
|
|
1706
1727
|
return self
|
|
1707
1728
|
|
|
1729
|
+
def get_image_metadata_dict(self) -> dict:
|
|
1730
|
+
"""Creates a nested dict of metadata.
|
|
1731
|
+
|
|
1732
|
+
The dict structure will be:
|
|
1733
|
+
|
|
1734
|
+
{
|
|
1735
|
+
image_path: {
|
|
1736
|
+
image_attribute: value,
|
|
1737
|
+
...,
|
|
1738
|
+
"bands": {
|
|
1739
|
+
band_id: {
|
|
1740
|
+
band_attribute: band_value,
|
|
1741
|
+
},
|
|
1742
|
+
...,
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
"""
|
|
1747
|
+
path = self.path
|
|
1748
|
+
metadata = {
|
|
1749
|
+
path: {
|
|
1750
|
+
"bounds": self.bounds,
|
|
1751
|
+
"crs": str(pyproj.CRS(self.crs).to_string()),
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
for key in self.metadata_attributes:
|
|
1755
|
+
metadata[path][key] = getattr(self, key)
|
|
1756
|
+
|
|
1757
|
+
metadata[path]["bands"] = {}
|
|
1758
|
+
for band in self:
|
|
1759
|
+
metadata[path]["bands"][band.band_id] = {}
|
|
1760
|
+
for key in band.metadata_attributes:
|
|
1761
|
+
if key in self.metadata_attributes:
|
|
1762
|
+
continue
|
|
1763
|
+
metadata[path]["bands"][band.band_id][key] = getattr(band, key)
|
|
1764
|
+
return metadata
|
|
1765
|
+
|
|
1766
|
+
def write_image_metadata(self) -> None:
|
|
1767
|
+
"""Write file 'metadata.json' under image path.
|
|
1768
|
+
|
|
1769
|
+
The file will be used to give the image attributes
|
|
1770
|
+
and avoid the much slower metadata fetching with rasterio.
|
|
1771
|
+
|
|
1772
|
+
See method 'get_image_metadata_dict' for info on the structure of
|
|
1773
|
+
the json file.
|
|
1774
|
+
"""
|
|
1775
|
+
metadata = self.get_image_metadata_dict()
|
|
1776
|
+
with _open_func(str(Path(self.path) / "metadata.json"), "w") as file:
|
|
1777
|
+
json.dump(metadata, file)
|
|
1778
|
+
|
|
1708
1779
|
def _construct_image_from_bands(
|
|
1709
1780
|
self, data: Sequence[Band], res: int | None
|
|
1710
1781
|
) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|