geo-explorer 0.9.11__tar.gz → 0.9.12__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.
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/PKG-INFO +1 -1
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/pyproject.toml +1 -1
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/src/geo_explorer/geo_explorer.py +55 -25
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/src/geo_explorer/img.py +8 -7
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/src/geo_explorer/utils.py +10 -6
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/LICENSE +0 -0
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/LICENSE.md +0 -0
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/README.md +0 -0
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/src/geo_explorer/__init__.py +0 -0
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/src/geo_explorer/assets/chroma.min.js +0 -0
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/src/geo_explorer/assets/on_each_feature.js +0 -0
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/src/geo_explorer/assets/stylesheet.css +0 -0
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/src/geo_explorer/file_browser.py +0 -0
- {geo_explorer-0.9.11 → geo_explorer-0.9.12}/src/geo_explorer/fs.py +0 -0
|
@@ -25,6 +25,7 @@ from typing import Any
|
|
|
25
25
|
from typing import ClassVar
|
|
26
26
|
|
|
27
27
|
import dash
|
|
28
|
+
import pyproj
|
|
28
29
|
import dash_bootstrap_components as dbc
|
|
29
30
|
import dash_leaflet as dl
|
|
30
31
|
import folium
|
|
@@ -686,12 +687,15 @@ def _read_files(explorer, paths: list[str], mask=None, **kwargs) -> None:
|
|
|
686
687
|
paths = [
|
|
687
688
|
path
|
|
688
689
|
for path in paths
|
|
689
|
-
if
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
690
|
+
if explorer._loaded_data_sizes[path] > 0
|
|
691
|
+
and (
|
|
692
|
+
mask is None
|
|
693
|
+
or (
|
|
694
|
+
path in bbox_set
|
|
695
|
+
and (
|
|
696
|
+
pd.isna(explorer._bbox_series[path])
|
|
697
|
+
or shapely.intersects(mask, explorer._bbox_series[path])
|
|
698
|
+
)
|
|
695
699
|
)
|
|
696
700
|
)
|
|
697
701
|
]
|
|
@@ -768,30 +772,55 @@ def _try_to_get_bbox_else_none(
|
|
|
768
772
|
|
|
769
773
|
|
|
770
774
|
def _get_bbox_series_as_4326(paths, file_system):
|
|
771
|
-
# bbox_series = sg.get_bbox_series(paths, file_system=file_system)
|
|
772
|
-
# return bbox_series.to_crs(4326)
|
|
773
|
-
|
|
774
775
|
func = partial(_try_to_get_bbox_else_none, file_system=file_system)
|
|
775
776
|
with ThreadPoolExecutor() as executor:
|
|
776
777
|
bbox_and_crs = list(executor.map(func, paths))
|
|
777
778
|
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
779
|
+
bbox_and_crs = [(bbox, json.dumps(crs)) for bbox, crs in bbox_and_crs]
|
|
780
|
+
bbox_and_crs = [
|
|
781
|
+
(
|
|
782
|
+
bbox,
|
|
783
|
+
(
|
|
784
|
+
pyproj.CRS(crs).to_string()
|
|
785
|
+
if not any(crs.lower() == txt for txt in ["none", "null"])
|
|
786
|
+
else None
|
|
787
|
+
),
|
|
788
|
+
)
|
|
789
|
+
for bbox, crs in bbox_and_crs
|
|
790
|
+
]
|
|
791
|
+
crss = {crs for (_, crs) in bbox_and_crs}
|
|
784
792
|
if not crss:
|
|
785
793
|
return GeoSeries([None for _ in range(len(paths))], index=paths)
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
794
|
+
missing = GeoSeries(
|
|
795
|
+
{
|
|
796
|
+
path: Polygon()
|
|
797
|
+
for path, (bbox, _) in zip(paths, bbox_and_crs, strict=True)
|
|
798
|
+
if bbox is None
|
|
799
|
+
}
|
|
800
|
+
)
|
|
801
|
+
paths_bbox_and_crs = {
|
|
802
|
+
path: (bbox, crs)
|
|
803
|
+
for path, (bbox, crs) in zip(paths, bbox_and_crs, strict=True)
|
|
804
|
+
if bbox is not None
|
|
805
|
+
}
|
|
806
|
+
crs_with_paths = {}
|
|
807
|
+
geoms = shapely.box(
|
|
808
|
+
[bbox[0] for (bbox, _) in paths_bbox_and_crs.values()],
|
|
809
|
+
[bbox[1] for (bbox, _) in paths_bbox_and_crs.values()],
|
|
810
|
+
[bbox[2] for (bbox, _) in paths_bbox_and_crs.values()],
|
|
811
|
+
[bbox[3] for (bbox, _) in paths_bbox_and_crs.values()],
|
|
812
|
+
)
|
|
813
|
+
for crs in crss:
|
|
814
|
+
crs_with_paths[crs] = {
|
|
815
|
+
path: geoms[i]
|
|
816
|
+
for i, (path, (bbox, this_crs)) in enumerate(paths_bbox_and_crs.items())
|
|
817
|
+
if this_crs == crs and bbox is not None
|
|
818
|
+
}
|
|
819
|
+
no_crs = GeoSeries(crs_with_paths.pop(None, {}), crs=4326)
|
|
820
|
+
return pd.concat(
|
|
821
|
+
[GeoSeries(data, crs=crs).to_crs(4326) for crs, data in crs_with_paths.items()]
|
|
822
|
+
+ [missing, no_crs]
|
|
823
|
+
)
|
|
795
824
|
|
|
796
825
|
|
|
797
826
|
def get_index(values: list[Any], ids: list[Any], index: Any):
|
|
@@ -2844,7 +2873,7 @@ class GeoExplorer:
|
|
|
2844
2873
|
self.color_dict = {}
|
|
2845
2874
|
elif not column and triggered is None:
|
|
2846
2875
|
column = self.column
|
|
2847
|
-
|
|
2876
|
+
if self._concatted_data is None:
|
|
2848
2877
|
return (
|
|
2849
2878
|
[],
|
|
2850
2879
|
None,
|
|
@@ -3151,6 +3180,7 @@ class GeoExplorer:
|
|
|
3151
3180
|
|
|
3152
3181
|
if images:
|
|
3153
3182
|
# make sure all single-band images are normalized by same extremities
|
|
3183
|
+
debug_print(images)
|
|
3154
3184
|
vmin = np.min([np.min(x[0]) for x in images.values()])
|
|
3155
3185
|
vmax = np.min([np.max(x[0]) for x in images.values()])
|
|
3156
3186
|
|
|
@@ -59,11 +59,9 @@ class AbstractImageConfig(abc.ABC):
|
|
|
59
59
|
clipped_bbox = bbox_correct_crs.intersection(shapely.box(*ds_bounds))
|
|
60
60
|
minx, miny, maxx, maxy = clipped_bbox.bounds
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
)
|
|
66
|
-
|
|
62
|
+
x = "x" if "x" in list(ds.coords) else "X"
|
|
63
|
+
y = "y" if "y" in list(ds.coords) else "Y"
|
|
64
|
+
ds = ds.sel(**{x: slice(minx, maxx), y: slice(maxy, miny)})
|
|
67
65
|
return self._run_code_block(ds)
|
|
68
66
|
|
|
69
67
|
@time_method_call(_PROFILE_DICT)
|
|
@@ -173,7 +171,7 @@ class NetCDFConfig(AbstractImageConfig):
|
|
|
173
171
|
for x in set(ds.attrs).union(
|
|
174
172
|
set(ds.data_vars if isinstance(ds, Dataset) else set())
|
|
175
173
|
)
|
|
176
|
-
if "projection" in x.lower() or "crs" in x.lower()
|
|
174
|
+
if "projection" in x.lower() or "crs" in x.lower() or "utm" in x.lower()
|
|
177
175
|
]
|
|
178
176
|
if not attrs:
|
|
179
177
|
raise ValueError(f"Could not find CRS attribute/data_var in dataset: {ds}")
|
|
@@ -181,7 +179,10 @@ class NetCDFConfig(AbstractImageConfig):
|
|
|
181
179
|
def getattr_xarray(ds, attr):
|
|
182
180
|
x = ds.attrs.get(attr, ds.get(attr))
|
|
183
181
|
if isinstance(x, DataArray):
|
|
184
|
-
|
|
182
|
+
try:
|
|
183
|
+
return pyproj.CRS(str(x.attrs["proj4"]))
|
|
184
|
+
except Exception:
|
|
185
|
+
return pyproj.CRS(str(x.values))
|
|
185
186
|
elif x is not None:
|
|
186
187
|
return pyproj.CRS(x)
|
|
187
188
|
raise ValueError(f"Could not find CRS attribute/data_var in dataset: {ds}")
|
|
@@ -91,9 +91,11 @@ def get_xarray_resolution(ds) -> int:
|
|
|
91
91
|
minx, miny, maxx, maxy = _get_raw_xarray_bounds(ds)
|
|
92
92
|
diffx = maxx - minx
|
|
93
93
|
diffy = maxy - miny
|
|
94
|
+
x = "x" if "x" in list(ds.coords) else "X"
|
|
95
|
+
y = "y" if "y" in list(ds.coords) else "Y"
|
|
94
96
|
try:
|
|
95
|
-
resx = diffx / (ds.sizes[
|
|
96
|
-
resy = diffy / (ds.sizes[
|
|
97
|
+
resx = diffx / (ds.sizes[x] - 1)
|
|
98
|
+
resy = diffy / (ds.sizes[y] - 1)
|
|
97
99
|
except ZeroDivisionError:
|
|
98
100
|
raise ValueError(
|
|
99
101
|
f"Cannot calculate resolution for Dataset with {diffx=}, {diffy=}, {ds.sizes['x']=}, {ds.sizes['y']=}"
|
|
@@ -117,11 +119,13 @@ def get_xarray_bounds(ds) -> tuple[float, float, float, float]:
|
|
|
117
119
|
|
|
118
120
|
|
|
119
121
|
def _get_raw_xarray_bounds(ds) -> tuple[float, float, float, float]:
|
|
122
|
+
x = "x" if "x" in list(ds.coords) else "X"
|
|
123
|
+
y = "y" if "y" in list(ds.coords) else "Y"
|
|
120
124
|
return (
|
|
121
|
-
float(ds[
|
|
122
|
-
float(ds[
|
|
123
|
-
float(ds[
|
|
124
|
-
float(ds[
|
|
125
|
+
float(ds[x].min().values),
|
|
126
|
+
float(ds[y].min().values),
|
|
127
|
+
float(ds[x].max().values),
|
|
128
|
+
float(ds[y].max().values),
|
|
125
129
|
)
|
|
126
130
|
|
|
127
131
|
|
|
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
|