ssb-sgis 1.0.5__py3-none-any.whl → 1.0.6__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/raster/indices.py CHANGED
@@ -1,18 +1,7 @@
1
- from collections.abc import Callable
2
-
3
1
  import numpy as np
4
- import pandas as pd
5
-
6
- from .raster import Raster
7
2
 
8
3
 
9
4
  def ndvi(red: np.ndarray, nir: np.ndarray) -> np.ndarray:
10
- # normalize red and nir arrays to 0-1 scale if needed
11
- # if red.max() > 1 and nir.max() > 1:
12
- # red = red / 255
13
- # nir = nir / 255
14
- # elif red.max() > 1 or nir.max() > 1:
15
- # raise ValueError()
16
5
  red = red / 255
17
6
  nir = nir / 255
18
7
 
@@ -20,82 +9,3 @@ def ndvi(red: np.ndarray, nir: np.ndarray) -> np.ndarray:
20
9
  ndvi_values[(red + nir) == 0] = 0
21
10
 
22
11
  return ndvi_values
23
-
24
-
25
- def gndvi(green: np.ndarray, nir: np.ndarray) -> np.ndarray:
26
- return np.where((green + nir) == 0, 0, (nir - green) / (nir + green))
27
-
28
-
29
- def water(green: np.ndarray, nir: np.ndarray) -> np.ndarray:
30
- return np.where((green + nir) == 0, 0, (green - nir) / (green + nir))
31
-
32
-
33
- def builtup(swir: np.ndarray, nir: np.ndarray) -> np.ndarray:
34
- return np.where((swir + nir) == 0, 0, (swir - nir) / (swir + nir))
35
-
36
-
37
- def moisture(swir: np.ndarray, nir: np.ndarray) -> np.ndarray:
38
- return np.where((swir + nir) == 0, 0, (nir - swir) / (nir + swir))
39
-
40
-
41
- def get_raster_pairs(
42
- cube,
43
- band_name1: str,
44
- band_name2: str,
45
- ) -> list[tuple[Raster, Raster]]:
46
- unique = pd.DataFrame({"tile": cube.tile, "date": cube.date}).drop_duplicates(
47
- ["tile", "date"]
48
- )
49
-
50
- raster_pairs = []
51
- for tile, date in zip(unique["tile"], unique["date"], strict=False):
52
- query = (cube.tile == tile) & (cube.date == date)
53
- band1 = cube.copy()[query & (cube.band == band_name1)]
54
- band2 = cube.copy()[query & (cube.band == band_name2)]
55
- if not len(band1) and not len(band2):
56
- continue
57
- if len(band1) > 1:
58
- raise ValueError("Cannot have more than one B4 band per tile.")
59
- if len(band2) > 1:
60
- raise ValueError("Cannot have more than one B8 band per tile.")
61
- if len(band1) != 1 and len(band2) != 1:
62
- raise ValueError("Must have one B4 and one B8 band per tile.")
63
- band1 = band1[0]
64
- band2 = band2[0]
65
- assert isinstance(band1, Raster), band1
66
- assert isinstance(band2, Raster), band2
67
-
68
- if band1.shape != band2.shape:
69
- raise ValueError("Rasters must have same shape")
70
-
71
- pair = band1, band2
72
- raster_pairs.append(pair)
73
-
74
- return raster_pairs
75
-
76
-
77
- def index_calc_pair(
78
- raster_pair: tuple[Raster, Raster], index_formula: Callable
79
- ) -> Raster:
80
- """Calculate an index for one raster pair and return a single Raster."""
81
- r1, r2 = raster_pair
82
- assert isinstance(r1, Raster), r1
83
- assert isinstance(r2, Raster), r2
84
-
85
- if r1.values is None:
86
- r1 = r1.load()
87
- if r2.values is None:
88
- r2 = r2.load()
89
-
90
- r1_arr: np.ndarray = r1.values.astype(np.float16)
91
- r2_arr: np.ndarray = r2.values.astype(np.float16)
92
-
93
- out_array = index_formula(r1_arr, r2_arr)
94
-
95
- return Raster.from_array(
96
- out_array,
97
- crs=r1.crs,
98
- bounds=r1.bounds,
99
- name=index_formula.__name__,
100
- date=r1.date,
101
- )
sgis/raster/regex.py ADDED
@@ -0,0 +1,146 @@
1
+ import itertools
2
+ import re
3
+ from collections.abc import Sequence
4
+
5
+ import pandas as pd
6
+
7
+ from ..io._is_dapla import is_dapla
8
+
9
+ try:
10
+ import dapla as dp
11
+ except ImportError:
12
+ pass
13
+
14
+ try:
15
+ from gcsfs.core import GCSFile
16
+ except ImportError:
17
+
18
+ class GCSFile:
19
+ """Placeholder."""
20
+
21
+
22
+ if is_dapla():
23
+
24
+ def _open_func(*args, **kwargs) -> GCSFile:
25
+ return dp.FileClient.get_gcs_file_system().open(*args, **kwargs)
26
+
27
+ else:
28
+ _open_func = open
29
+
30
+
31
+ class _RegexError(ValueError):
32
+ pass
33
+
34
+
35
+ def _any_regex_matches(xml_file: str, regexes: tuple[str]) -> bool:
36
+ for regex in regexes:
37
+ try:
38
+ if bool(re.search(regex, xml_file)):
39
+ return True
40
+ except (TypeError, AttributeError):
41
+ continue
42
+
43
+ return False
44
+
45
+
46
+ def _get_regex_match_from_xml_in_local_dir(
47
+ paths: list[str], regexes: str | tuple[str]
48
+ ) -> str | dict[str, str]:
49
+ for i, path in enumerate(paths):
50
+ if ".xml" not in path:
51
+ continue
52
+ with _open_func(path, "rb") as file:
53
+ filebytes: bytes = file.read()
54
+ try:
55
+ return _extract_regex_match_from_string(
56
+ filebytes.decode("utf-8"), regexes
57
+ )
58
+ except _RegexError as e:
59
+ if i == len(paths) - 1:
60
+ raise e
61
+
62
+
63
+ def _extract_regex_match_from_string(
64
+ xml_file: str, regexes: tuple[str | re.Pattern]
65
+ ) -> str | dict[str, str]:
66
+ if all(isinstance(x, str) for x in regexes):
67
+ for regex in regexes:
68
+ try:
69
+ return re.search(regex, xml_file).group(1)
70
+ except (TypeError, AttributeError, IndexError):
71
+ continue
72
+ raise _RegexError()
73
+
74
+ out = {}
75
+ for regex in regexes:
76
+ try:
77
+ matches = re.search(regex, xml_file)
78
+ out |= matches.groupdict()
79
+ except (TypeError, AttributeError):
80
+ continue
81
+ if not out:
82
+ raise _RegexError()
83
+ return out
84
+
85
+
86
+ def _get_regexes_matches_for_df(
87
+ df, match_col: str, patterns: Sequence[re.Pattern]
88
+ ) -> pd.DataFrame:
89
+ if not len(df):
90
+ return df
91
+
92
+ non_optional_groups = list(
93
+ set(
94
+ itertools.chain.from_iterable(
95
+ [_get_non_optional_groups(pat) for pat in patterns]
96
+ )
97
+ )
98
+ )
99
+
100
+ if not non_optional_groups:
101
+ return df
102
+
103
+ assert df.index.is_unique
104
+ keep = []
105
+ for pat in patterns:
106
+ for i, row in df[match_col].items():
107
+ matches = _get_first_group_match(pat, row)
108
+ if all(group in matches for group in non_optional_groups):
109
+ keep.append(i)
110
+
111
+ return df.loc[keep]
112
+
113
+
114
+ def _get_non_optional_groups(pat: re.Pattern | str) -> list[str]:
115
+ return [
116
+ x
117
+ for x in [
118
+ _extract_group_name(group)
119
+ for group in pat.pattern.split("\n")
120
+ if group
121
+ and not group.replace(" ", "").startswith("#")
122
+ and not group.replace(" ", "").split("#")[0].endswith("?")
123
+ ]
124
+ if x is not None
125
+ ]
126
+
127
+
128
+ def _extract_group_name(txt: str) -> str | None:
129
+ try:
130
+ return re.search(r"\(\?P<(\w+)>", txt)[1]
131
+ except TypeError:
132
+ return None
133
+
134
+
135
+ def _get_first_group_match(pat: re.Pattern, text: str) -> dict[str, str]:
136
+ groups = pat.groupindex.keys()
137
+ all_matches: dict[str, str] = {}
138
+ for x in pat.findall(text):
139
+ if not x:
140
+ continue
141
+ if isinstance(x, str):
142
+ x = [x]
143
+ for group, value in zip(groups, x, strict=True):
144
+ if value and group not in all_matches:
145
+ all_matches[group] = value
146
+ return all_matches
@@ -60,6 +60,15 @@ CLOUD_COVERAGE_REGEXES: tuple[str] = (
60
60
  r"<CLOUDY_PIXEL_OVER_LAND_PERCENTAGE>([\d.]+)</CLOUDY_PIXEL_OVER_LAND_PERCENTAGE>",
61
61
  )
62
62
 
63
+ BOA_QUANTIFICATION_VALUE_REGEXES: tuple[str] = (
64
+ r'<BOA_QUANTIFICATION_VALUE unit="none">(\d+)</BOA_QUANTIFICATION_VALUE>',
65
+ )
66
+
67
+ PROCESSING_BASELINE_REGEXES: tuple[str] = (
68
+ r"<PROCESSING_BASELINE>(.*?)</PROCESSING_BASELINE>",
69
+ )
70
+
71
+
63
72
  CRS_REGEXES: tuple[str] = (r"<HORIZONTAL_CS_CODE>EPSG:(\d+)</HORIZONTAL_CS_CODE>",)
64
73
 
65
74
  BOUNDS_REGEXES: tuple[dict[str, str]] = (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ssb-sgis
3
- Version: 1.0.5
3
+ Version: 1.0.6
4
4
  Summary: GIS functions used at Statistics Norway.
5
5
  Home-page: https://github.com/statisticsnorway/ssb-sgis
6
6
  License: MIT
@@ -1,16 +1,16 @@
1
- sgis/__init__.py,sha256=wuANmvvdEus5xumwqVXC1xUUDajThjYuS5jBwfPYCeI,7266
2
- sgis/debug_config.py,sha256=hIJEz3cIDjoxrtRMuVcNQSXZHCRTbh63Tri4IR7iVFM,545
1
+ sgis/__init__.py,sha256=kqHf60QUo0_TaB1ikBQXkxCQK4hUjSM6u_GKfLJ3C-4,7351
2
+ sgis/debug_config.py,sha256=Tfr19kU46hSkkspsIJcrUWvlhaL4U3-f8xEPkujSCAQ,593
3
3
  sgis/exceptions.py,sha256=WNaEBPNNx0rmz-YDzlFX4vIE7ocJQruUTqS2RNAu2zU,660
4
4
  sgis/geopandas_tools/__init__.py,sha256=bo8lFMcltOz7TtWAi52_ekR2gd3mjfBfKeMDV5zuqFY,28
5
5
  sgis/geopandas_tools/bounds.py,sha256=iIIqacQafn4XrWDaJtaffLrW72z3ce_-YYwdTtWmA8E,23673
6
- sgis/geopandas_tools/buffer_dissolve_explode.py,sha256=_0XgfC4DSUEKF4sbGr2KpMSngCrPrZt_d7siy0vILLU,21083
6
+ sgis/geopandas_tools/buffer_dissolve_explode.py,sha256=5Dy-HfLm-n4IjlLm98Wtufl4IuCw0Zglyy5VlEH0mak,19955
7
7
  sgis/geopandas_tools/centerlines.py,sha256=Q65Sx01SeAlulBEd9oaZkB2maBBNdLcJwAbTILg4SPU,11848
8
8
  sgis/geopandas_tools/cleaning.py,sha256=I3tpn5uzsLjRYi-TybUe3QuNns0CseuxkfBSmSMer0I,60208
9
- sgis/geopandas_tools/conversion.py,sha256=TkfSu-DRHicH8LSR7ygMN84ggxP_zzmFk54iLNv1ftg,24660
9
+ sgis/geopandas_tools/conversion.py,sha256=Cl_8tYvR0eRi26CPK2ZnIorYXJZ2vkNiDqe0VzSDVaE,25461
10
10
  sgis/geopandas_tools/duplicates.py,sha256=LG8-BG8LdA2zjWauuloslIZHvMGND6Fja0MtXIPZ1wo,14301
11
- sgis/geopandas_tools/general.py,sha256=5ZD7CXGIvJmWDN-V-RlG0K_mWiT6iVNvP_UL8cufk2A,31651
11
+ sgis/geopandas_tools/general.py,sha256=_XpQf792JqkvnMvEqtUMkPGVhjsct2SHSAyDYFdCyuQ,39885
12
12
  sgis/geopandas_tools/geocoding.py,sha256=n47aFQMm4yX1MsPnTM4dFjwegCA1ZmGUDj1uyu7OJV4,691
13
- sgis/geopandas_tools/geometry_types.py,sha256=hSlN8n4pJZPkEfOdKL1DRux757kl81DciIH7ZXiHEdE,7587
13
+ sgis/geopandas_tools/geometry_types.py,sha256=ijQDbQaZPqPGjBl707H4yooNXpk21RXyatI7itnvqLk,7603
14
14
  sgis/geopandas_tools/neighbors.py,sha256=vduQlHeoZjHyD5pxDbjfonQ3-LAHGfPETxV7-L6Sg4M,16634
15
15
  sgis/geopandas_tools/overlay.py,sha256=pfRSvHmX7GXkJDkpMQvNgS6LTF6DirzrEZCVPSHDUBs,25582
16
16
  sgis/geopandas_tools/point_operations.py,sha256=JM4hvfIVxZaZdGNlGzcCurrKzkgC_b9hzbFYN42f9WY,6972
@@ -19,16 +19,16 @@ sgis/geopandas_tools/polygons_as_rings.py,sha256=BX_GZS6F9I4NbEpiOlNBd7zywJjdfdJ
19
19
  sgis/geopandas_tools/sfilter.py,sha256=SLcMYprQwnY5DNo0R7TGXk4m6u26H8o4PRn-RPhmeZY,9345
20
20
  sgis/helpers.py,sha256=dscvGAbZyyncZbTL9qdsAHN6tb_T7SbNH7vM4ZrTeJw,8326
21
21
  sgis/io/_is_dapla.py,sha256=o_qFD5GOi3dsSGOKmW6R8wZU0htVwFgRbGX7ppJCqT4,431
22
- sgis/io/dapla_functions.py,sha256=Y69aSjnw6rOpH8yIquNor-JoTXcUfjbx2FcduT72-1A,17654
22
+ sgis/io/dapla_functions.py,sha256=8dfxBtkGUy7vltlKydXkathBsSd9DPHVIDIOe-Ctjsg,18180
23
23
  sgis/io/opener.py,sha256=BHyH7L8Ubh9C4Lsb8eBzGI6FLWg8UQFu-1bg3NEy_2k,862
24
24
  sgis/io/read_parquet.py,sha256=FvZYv1rLkUlrSaUY6QW6E1yntmntTeQuZ9ZRgCDO4IM,3776
25
25
  sgis/maps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  sgis/maps/examine.py,sha256=Pb0dH8JazU5E2svfQrzHO1Bi-sjy5SeyY6zoeMO34jE,9369
27
- sgis/maps/explore.py,sha256=K-iJ07v_srUB_Z6hTuSRSKqgljKewY9A_j14bSrs0Yg,45916
27
+ sgis/maps/explore.py,sha256=QEzJ9Qb5rCGS9TVGG8vZsIdVwVPAngeUvwJG2igoEio,46215
28
28
  sgis/maps/httpserver.py,sha256=7Od9JMCtntcIQKk_TchetojMHzFHT9sPw7GANahI97c,1982
29
29
  sgis/maps/legend.py,sha256=1ZOhzftq1HRKlHphhfqUm82U-Kjx_xkACieLRevxke8,26232
30
- sgis/maps/map.py,sha256=LHXFl_f5OWcPesKvwr-4L91Hd0VFFXNSGMQXaqmszMg,29276
31
- sgis/maps/maps.py,sha256=GgvxwRY0Sz2e432Emj6i8hAp6sFduKt9VhsWw9HgKI4,23147
30
+ sgis/maps/map.py,sha256=B5VfOdzp4xadNWbNJzHJueIfcrZYGthrM0CnSPedyUs,29392
31
+ sgis/maps/maps.py,sha256=HbKG1OHkSFYZ2dpgpag6H-LY1tOtZKaZncNNrBQpkU4,23127
32
32
  sgis/maps/thematicmap.py,sha256=bFlZy2xSKmEOHhvM0d1pv8O9JuNjR3P_9colTJnduvE,20729
33
33
  sgis/maps/tilesources.py,sha256=aSci-0JURxnqqirIXQS5bHfNEIg3xfCM_B4gXs7GslM,2772
34
34
  sgis/networkanalysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -36,27 +36,25 @@ sgis/networkanalysis/_get_route.py,sha256=9I3t9pnccUPr4mozy3TJCOpGCCf3UOIojmsbif
36
36
  sgis/networkanalysis/_od_cost_matrix.py,sha256=zkyPX7ObT996ahaFJ2oI0D0SqQWbWyfy_qLtXwValPg,3434
37
37
  sgis/networkanalysis/_points.py,sha256=ajCy17dAmRq3bWRkNu_0LHreCVJ5Uh8DzAKWxyw7ipw,4481
38
38
  sgis/networkanalysis/_service_area.py,sha256=jE0X54yS4eMfZYJXeKe_NgMKPDpau-05xWZaxDi_c6Y,5546
39
- sgis/networkanalysis/closing_network_holes.py,sha256=EyhsLnjD6omTVgH9HIznukIX-vIOTtkv8_pwUnR6Pvk,12095
40
- sgis/networkanalysis/cutting_lines.py,sha256=Uo6sGdC1xhkWwO69wgQYgGdT1JS6ZfZzHm8JrM1GmZM,15420
39
+ sgis/networkanalysis/closing_network_holes.py,sha256=FYZ677nRwLmDkP6bQ1ssQ_h29RzAG463U4xmbu5ksfg,14572
40
+ sgis/networkanalysis/cutting_lines.py,sha256=ZQAt0cufaPeNAEqUzp-imu26AIL9S5-lw6Xifa8RoWk,9818
41
41
  sgis/networkanalysis/directednetwork.py,sha256=Mrc2zHip4P5RNxnyffKm-xU832AVQeSHz-YZueAc0pM,11413
42
- sgis/networkanalysis/finding_isolated_networks.py,sha256=s7knwQJeNqU6wJ9gIwwYnSAwGyKH98zZ2NroxZnTQxI,3637
42
+ sgis/networkanalysis/finding_isolated_networks.py,sha256=Wg4ILhm7uS9RLOGcL0WN8uZBMJYjdljJc8L5DU5nIPY,3754
43
43
  sgis/networkanalysis/network.py,sha256=zV9bAbVdTgTohg2o2RFGy2uhOJrd3Ma57hwIAStxMAQ,7847
44
44
  sgis/networkanalysis/networkanalysis.py,sha256=-g7slZLFNxUZSUMvVmf7zax-9IOXz1NGCtR6LcsBzBQ,68476
45
45
  sgis/networkanalysis/networkanalysisrules.py,sha256=9sXigaCzvKhXFwpeVNMtOiIK3_Hzp9yDpFklmEEAPak,12956
46
- sgis/networkanalysis/nodes.py,sha256=Yo0oWlsZO0Ex2_7lzGGUEiS2Ltfnm5kuCl5MkE2qJhA,6863
46
+ sgis/networkanalysis/nodes.py,sha256=atFSpqz-_uJHMrf6MC0zhrrcWIydRMFZrsaHC2xr1GU,3374
47
47
  sgis/networkanalysis/traveling_salesman.py,sha256=Jjo6bHY4KJ-eK0LycyTy0sWxZjgITs5MBllZ_G9FhTE,5655
48
- sgis/parallel/parallel.py,sha256=4Juv3oepguP4XryrgfbX-ipbYunKmbxvzM0jj8kYpCE,37296
48
+ sgis/parallel/parallel.py,sha256=SlC_mOwvSSyWTKUcxLMGkuWHUkEC6dXTlN0Jn5cAtxA,39687
49
49
  sgis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
50
  sgis/raster/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
51
  sgis/raster/base.py,sha256=8J6y9k-YuCAUpE83yTkg26RF2YCp9aieVvWrPi_GfUc,7697
52
- sgis/raster/cube.py,sha256=P9baGN03Mwdi_LJ5a3F9_PROVYGCbjopQSxwQnr1LvE,41764
53
- sgis/raster/cubebase.py,sha256=nao5huLer-nzy792PTZc0CKAMlmedZCe3siWnOf7Duw,639
54
- sgis/raster/image_collection.py,sha256=giG922K2onunjbjxjDxFGADgvGFkrWm6_9EAwqq9mho,106275
55
- sgis/raster/indices.py,sha256=bb0ItG8ePoFsrc5-XSupnMzJ6EwoALGh-lscM81Gpfo,3010
56
- sgis/raster/raster.py,sha256=I8Af6gRIexvrNWTGBfZX6WC0Eug07Vykam4EaP1ZUws,50576
57
- sgis/raster/sentinel_config.py,sha256=zcw24T9RBqix85QGK35LAYWuEkHJEwMcDRcnApRpLHs,3019
52
+ sgis/raster/image_collection.py,sha256=uRQ_0qimViSY0O29fP0aa1M6Z-KPjIyAZKy4W2K_65I,105123
53
+ sgis/raster/indices.py,sha256=OoFb53xcBm-9CZIvvydFWFgrenJ_lgt25yVo-imCrSM,226
54
+ sgis/raster/regex.py,sha256=6zhOgUFkXQv05nXBdTkkk6jdPuiIQCUgkTHBwYeE-zA,3637
55
+ sgis/raster/sentinel_config.py,sha256=-vYglbUouMkmH3wiGTL9MVSKTIrWHQcZYjKqtXNIuQo,3255
58
56
  sgis/raster/zonal.py,sha256=st2mWiUcdxeEiHBOZSgFOnVcP6pc4EMPJBPw537Z4V8,3837
59
- ssb_sgis-1.0.5.dist-info/LICENSE,sha256=np3IfD5m0ZUofn_kVzDZqliozuiO6wrktw3LRPjyEiI,1073
60
- ssb_sgis-1.0.5.dist-info/METADATA,sha256=S5f4hjaAml8BRNW9jSIvJVvCmSKol3N6VGGM1VhY3-s,11772
61
- ssb_sgis-1.0.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
62
- ssb_sgis-1.0.5.dist-info/RECORD,,
57
+ ssb_sgis-1.0.6.dist-info/LICENSE,sha256=np3IfD5m0ZUofn_kVzDZqliozuiO6wrktw3LRPjyEiI,1073
58
+ ssb_sgis-1.0.6.dist-info/METADATA,sha256=CmI9NHsFRCPUKajae6dAu2EFmacFxYSeVKCa1K9sgqw,11772
59
+ ssb_sgis-1.0.6.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
60
+ ssb_sgis-1.0.6.dist-info/RECORD,,