Skip to content

Commit 838316b

Browse files
XanthosXanthopoulosMargrietGroenendijkSarantopoulosKon
authored
Tiled Image parameters update (#62)
* initial changes - wip * image viewer added - wip * add image viewer * Removed unses polyfill plugin, update tiled image parameters * Updated dependencies * Bump TileDB Viz version to 1.0.2-alpha.12 * lint fix * Pin capnp-ts to 0.4.0 * Remove packageManager entry since jlab v3 uses yarn v1 --------- Co-authored-by: Margriet Groenendijk <[email protected]> Co-authored-by: SarantopoulosKon <[email protected]>
1 parent 020a961 commit 838316b

11 files changed

+4126
-5417
lines changed

.yarnrc.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
enableImmutableInstalls: false
2-
nodeLinker: node-modules
2+
3+
nodeLinker: node-modules

package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
"dependencies": {
5959
"@jupyter-widgets/base": "^2 || ^3 || ^4 || ^5 || ^6",
6060
"@jupyterlab/application": "^3 || ^4",
61-
"@tiledb-inc/viz-core": "^1.0.2-alpha.2"
61+
"@tiledb-inc/viz-core": "1.0.2-alpha.12"
6262
},
6363
"devDependencies": {
6464
"@jupyterlab/builder": "^3 || ^4",
@@ -86,6 +86,9 @@
8686
"webpack": "^5.88.1",
8787
"webpack-cli": "^5.1.4"
8888
},
89+
"resolutions": {
90+
"capnp-ts": "0.4.0"
91+
},
8992
"jupyterlab": {
9093
"extension": "lib/plugin",
9194
"outputDir": "pybabylonjs/labextension",

pybabylonjs/args.py

+54-52
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,13 @@
1515
"inspector": None,
1616
"color_scheme": None,
1717
"z_scale": None,
18-
"topo_offset": None,
19-
"classes": {"numbers": [], "names": []},
20-
"time_offset": None,
21-
"point_shift": [None, None, None],
2218
"rgb_max": None,
2319
"bbox": None,
2420
"name_space": None,
2521
"group_name": None,
2622
"array_name": None,
2723
"token": None,
2824
"tiledb_env": None,
29-
"mbtoken": None,
30-
"mbstyle": None,
3125
"crs": None,
3226
"buffer_size": None,
3327
"streaming": None,
@@ -46,45 +40,65 @@
4640
"worker_pool_size": None,
4741
}
4842

43+
IMAGE_ARGS_DEFAULTS = {
44+
"width": None,
45+
"height": None,
46+
"wheel_precision": None, # used? in base class?
47+
"move_speed": None, # used?
48+
"name_space": None,
49+
"array_name": None,
50+
"group_name": None,
51+
"geometry_array_name": None,
52+
"base_group": None,
53+
"token": None,
54+
"tiledb_env": None,
55+
"default_channels": None,
56+
}
4957

50-
def check_point_cloud_args(source, mode, point_cloud_args_in):
51-
if mode == "time":
52-
raise ValueError("This mode will be implemented soon")
53-
if mode == "classes":
54-
raise ValueError("This mode will be implemented soon")
55-
if not "classes" in point_cloud_args_in:
56-
raise ValueError(
57-
"The classes containing numbers and names is not specified"
58-
)
59-
elif mode == "topo":
60-
raise ValueError("This mode will be implemented soon")
61-
if not "mbtoken" in point_cloud_args_in:
62-
raise ValueError("The Mapbox token is not specified")
63-
if not "crs" in point_cloud_args_in:
64-
raise ValueError(
65-
"The crs (coordinate reference system) of the data is not specified"
66-
)
67-
if not "bbox" in point_cloud_args_in:
68-
raise ValueError("The bbox is not specified")
6958

59+
def in_pixels(h, default):
60+
if h is None:
61+
return default
62+
if isinstance(h, str):
63+
if "px" in h:
64+
return h
65+
return h + "px"
66+
if isinstance(h, int):
67+
return str(h) + "px"
68+
if isinstance(h, float):
69+
return str(int(h)) + "px"
70+
71+
72+
def check_image_args(image_args_in):
73+
image_args = {}
74+
for key in IMAGE_ARGS_DEFAULTS.keys():
75+
if key in image_args_in:
76+
if key is not None:
77+
image_args[key] = image_args_in.pop(key)
78+
79+
image_args["height"] = in_pixels(image_args.get("height"), "500px")
80+
image_args["width"] = in_pixels(image_args.get("width"), "700px")
81+
82+
if not "token" in image_args:
83+
try:
84+
token = os.getenv("TILEDB_REST_TOKEN")
85+
except:
86+
if token == None:
87+
raise ValueError(
88+
"The TileDB Cloud token needed to access the array is not specified or cannot be accessed"
89+
)
90+
image_args = {**image_args, "token": token}
91+
92+
return image_args
93+
94+
95+
def check_point_cloud_args(source, streaming, point_cloud_args_in):
7096
point_cloud_args = {}
7197
for key in POINT_CLOUD_ARGS_DEFAULTS.keys():
7298
if key in point_cloud_args_in:
7399
if key is not None:
74100
point_cloud_args[key] = point_cloud_args_in.pop(key)
75101

76-
def in_pixels(h, default):
77-
if h is None:
78-
return default
79-
if isinstance(h, str):
80-
if "px" in h:
81-
return h
82-
return h + "px"
83-
if isinstance(h, int):
84-
return str(h) + "px"
85-
if isinstance(h, float):
86-
return str(int(h)) + "px"
87-
88102
point_cloud_args["height"] = in_pixels(point_cloud_args.get("height"), "500px")
89103
point_cloud_args["width"] = in_pixels(point_cloud_args.get("width"), "700px")
90104

@@ -101,7 +115,7 @@ def in_pixels(h, default):
101115
return point_cloud_args
102116

103117

104-
def check_point_cloud_data_dict(mode, data):
118+
def check_point_cloud_data_dict(data):
105119
for var in ["X", "Y", "Z", "Red", "Green", "Blue"]:
106120
if not var in data:
107121
raise ValueError("Data dictionary does not contain " + var)
@@ -115,28 +129,16 @@ def check_point_cloud_data_dict(mode, data):
115129
):
116130
raise ValueError("Attributes in data dictionary do not have the same length.")
117131

118-
if mode == "time":
119-
if not "GpsTime" in data:
120-
raise ValueError("Data dictionary does not contain 'GpsTime'")
121-
122-
i = np.argsort(data["GpsTime"])
123-
for key in ["Red", "Green", "Blue", "GpsTime", "X", "Y", "Z"]:
124-
data[key] = data[key][i]
125-
126-
elif mode == "classes":
127-
if not "Classification" in data:
128-
raise ValueError("Data dictionary does not contain 'Classification'")
129-
130132
return data
131133

132134

133-
def check_point_cloud_data_local(mode, uri, point_cloud_args):
135+
def check_point_cloud_data_local(uri, point_cloud_args):
134136
if os.path.isdir(uri) == False:
135137
raise ValueError("uri: " + uri + " does not exist.")
136138
if not "bbox" in point_cloud_args:
137139
raise ValueError("The bbox for slicing data from the array is not specified")
138140

139-
data = create_point_cloud(mode, uri, point_cloud_args["bbox"])
141+
data = create_point_cloud(uri, point_cloud_args["bbox"])
140142

141143
return data
142144

pybabylonjs/babylonjs.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ class BabylonMBRS(BabylonBase):
4646

4747
@register
4848
class BabylonImage(BabylonBase):
49-
"""Ground surface as 2D array with BabylonJS"""
49+
"""Images with BabylonJS"""
5050

51-
_model_name = Unicode("BabylonImageModel").tag(sync=True)
52-
_view_name = Unicode("BabylonImageView").tag(sync=True)
51+
_model_name = Unicode("BabylonTileImageModel").tag(sync=True)
52+
_view_name = Unicode("BabylonTileImageView").tag(sync=True)
5353
value = Dict().tag(sync=True)

pybabylonjs/data.py

+2-108
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,12 @@
22
# Licensed under the MIT License.
33
"""Functions to format data from the arrays to be used in the visualization."""
44

5-
import io
6-
import numpy as np
75
import pandas as pd
8-
import cv2
96
import tiledb
107

118

12-
def create_point_cloud(mode, array_uri: str, bbox):
13-
if mode == "time":
14-
attrs = ["Red", "Green", "Blue", "GpsTime"]
15-
elif mode == "classes":
16-
attrs = ["Red", "Green", "Blue", "Classification"]
17-
else:
18-
attrs = ["Red", "Green", "Blue"]
9+
def create_point_cloud(array_uri: str, bbox):
10+
attrs = ["Red", "Green", "Blue"]
1911

2012
with tiledb.open(array_uri) as arr:
2113
data = arr.query(attrs=attrs, dims=["X", "Y", "Z"])[
@@ -24,75 +16,9 @@ def create_point_cloud(mode, array_uri: str, bbox):
2416
bbox["Z"][0] : bbox["Z"][1],
2517
]
2618

27-
if mode == "time":
28-
i = np.argsort(data["GpsTime"])
29-
for key in ["Red", "Green", "Blue", "GpsTime", "X", "Y", "Z"]:
30-
data[key] = data[key][i]
31-
3219
return data
3320

3421

35-
def create_mapbox_image(data: dict, point_cloud_args):
36-
"""Create a Dict with an additional topographic image from mapbox
37-
38-
Parameters:
39-
"""
40-
import requests
41-
from rasterio.coords import BoundingBox
42-
from rasterio.warp import transform_bounds
43-
44-
mbtoken = point_cloud_args["mbtoken"]
45-
style_id = point_cloud_args["mbstyle"]
46-
data_crs = point_cloud_args["crs"]
47-
bbox_in = point_cloud_args["bbox"]
48-
49-
dst_crs = {"init": "EPSG:4326"} # lat/lon
50-
51-
if bbox_in:
52-
bbox = BoundingBox(
53-
bbox_in["X"][0], bbox_in["Y"][0], bbox_in["X"][1], bbox_in["Y"][1]
54-
)
55-
else:
56-
bbox = BoundingBox(
57-
data["X"].min(), data["Y"].min(), data["X"].max(), data["Y"].max()
58-
)
59-
60-
dst_bbox = transform_bounds(data_crs, dst_crs, *bbox)
61-
62-
w = bbox[2] - bbox[0]
63-
h = bbox[3] - bbox[1]
64-
65-
if w > h:
66-
ww = 1280
67-
hh = int(h / w * 1280)
68-
elif h > w:
69-
hh = 1280
70-
ww = int(w / h * 1280)
71-
72-
f = requests.get(
73-
(
74-
"https://api.mapbox.com/styles/v1/mapbox/"
75-
+ style_id
76-
+ "/static/["
77-
+ str(dst_bbox[0])
78-
+ ","
79-
+ str(dst_bbox[1])
80-
+ ","
81-
+ str(dst_bbox[2])
82-
+ ","
83-
+ str(dst_bbox[3])
84-
+ "]/"
85-
+ str(ww)
86-
+ "x"
87-
+ str(hh)
88-
+ "?access_token="
89-
+ mbtoken
90-
)
91-
)
92-
93-
return f.content
94-
95-
9622
def create_mbrs(array_uri: str):
9723
"""Create a Dict to be passed on to BabylonMBRS to create MBRS outlines."""
9824
fragments_info = tiledb.array_fragments(array_uri, include_mbrs=True)
@@ -137,35 +63,3 @@ def create_mbrs(array_uri: str):
13763
]
13864

13965
return dict(extents=extents, data=data)
140-
141-
142-
def create_image(array_uri: str, **kwargs):
143-
"""Create a Dict to be passed on to BabylonGround containing images as blobs.
144-
145-
Parameters:
146-
array_uri: uri of the dense array
147-
attribute: the attribute to load from the array
148-
xy_bbox: ranges of x and y to slice data on [x1,x2,y1,y2]
149-
band: band number to slice from the array
150-
scale_factor: factor to scale the values in the image
151-
"""
152-
153-
def numpy_to_binary(arr):
154-
is_success, buffer = cv2.imencode(".png", arr)
155-
io_buf = io.BytesIO(buffer)
156-
return io_buf.read()
157-
158-
bbox = kwargs["xy_bbox"]
159-
band = kwargs["band"]
160-
image_type = kwargs["image_type"]
161-
sar_scale = kwargs["sar_scale_factor"]
162-
163-
with tiledb.open(array_uri, "r") as arr:
164-
img = arr[band, bbox[0] : bbox[1], bbox[2] : bbox[3]][kwargs["attribute"]]
165-
166-
if image_type == "sar":
167-
img = 20 * np.log10(img * sar_scale)
168-
img = ((img - np.min(img)) / (np.max(img) - np.min(img))) * 255
169-
binary_image = numpy_to_binary(img)
170-
171-
return dict(data=binary_image)

0 commit comments

Comments
 (0)