Skip to content

Commit 6ac6de4

Browse files
Merge pull request developmentseed#22 from developmentseed/patch/adjust-colormap-rescale
adjust rescale and colormap render params
2 parents aaf4249 + e9829bb commit 6ac6de4

File tree

3 files changed

+256
-16
lines changed

3 files changed

+256
-16
lines changed

tests/fixtures/catalog.json

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
{
2+
"collections": [
3+
{
4+
"id": "MAXAR_BayofBengal_Cyclone_Mocha_May_23",
5+
"type": "Collection",
6+
"links": [
7+
{
8+
"rel": "items",
9+
"type": "application/geo+json",
10+
"href": "https://stac.endpoint.io/collections/MAXAR_BayofBengal_Cyclone_Mocha_May_23/items"
11+
},
12+
{
13+
"rel": "parent",
14+
"type": "application/json",
15+
"href": "https://stac.endpoint.io/"
16+
},
17+
{
18+
"rel": "root",
19+
"type": "application/json",
20+
"href": "https://stac.endpoint.io/"
21+
},
22+
{
23+
"rel": "self",
24+
"type": "application/json",
25+
"href": "https://stac.endpoint.io/collections/MAXAR_BayofBengal_Cyclone_Mocha_May_23"
26+
}
27+
],
28+
"title": "Bay of Bengal Cyclone Mocha 2023",
29+
"extent": {
30+
"spatial": {
31+
"bbox": [
32+
[
33+
91.831615,
34+
19.982078842323997,
35+
92.97426268500965,
36+
21.666101
37+
],
38+
[
39+
92.567815,
40+
20.18811887678192,
41+
92.74417544237298,
42+
20.62968532404085
43+
],
44+
[
45+
92.72278776887262,
46+
20.104801,
47+
92.893524,
48+
20.630214
49+
],
50+
[
51+
92.75855246040959,
52+
19.982078842323997,
53+
92.89682495377032,
54+
20.514473160464657
55+
],
56+
[
57+
92.84253515935835,
58+
19.984656587012033,
59+
92.97426268500965,
60+
20.514418665444474
61+
],
62+
[
63+
91.831615,
64+
21.518411,
65+
91.957078,
66+
21.666101
67+
]
68+
]
69+
},
70+
"temporal": {
71+
"interval": [
72+
[
73+
"2023-01-03T04:30:17Z",
74+
"2023-05-22T04:35:25Z"
75+
]
76+
]
77+
}
78+
},
79+
"license": "CC-BY-NC-4.0",
80+
"renders": {
81+
"visual": {
82+
"title": "Visual Image",
83+
"assets": [
84+
"visual"
85+
],
86+
"asset_bidx": "visual|1,2,3",
87+
"minmax_zoom": [
88+
8,
89+
22
90+
],
91+
"tilematrixsets": {
92+
"WebMercatorQuad": [
93+
8,
94+
22
95+
]
96+
}
97+
},
98+
"color": {
99+
"title": "Colored Image",
100+
"assets": [
101+
"visual"
102+
],
103+
"asset_bidx": "visual|1",
104+
"colormap": {
105+
"1": [0, 0, 0, 255],
106+
"1000": [255, 255, 255, 255]
107+
}
108+
},
109+
"visualr": {
110+
"title": "Rescaled Image",
111+
"assets": [
112+
"visual"
113+
],
114+
"asset_bidx": "visual|1",
115+
"rescale": [
116+
[0, 100]
117+
]
118+
}
119+
},
120+
"description": "Maxar OpenData | Cyclone Mocha, a category five cyclone with 130 mph winds and torrential rain, hit parts of Myanmar and Bangladesh, forcing mass evacuations ahead of the storm. The cyclone, one of the most powerful to hit the region in the last decade, made landfall on Sunday, May 14, 2023, near Sittwe in Myanmar's Rakhine state. Rain and a storm surge caused widespread flooding in low-lying areas. The United National Office Coordination of Humanitarian Affairs stated that there had been extensive damage among already vulnerable communities and that communications with the affected areas have been difficult.",
121+
"item_assets": {
122+
"visual": {
123+
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
124+
"roles": [
125+
"visual"
126+
],
127+
"title": "Visual Image"
128+
},
129+
"data-mask": {
130+
"type": "application/geopackage+sqlite3",
131+
"roles": [
132+
"data-mask"
133+
],
134+
"title": "Data Mask"
135+
},
136+
"ms_analytic": {
137+
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
138+
"roles": [
139+
"data"
140+
],
141+
"title": "Multispectral Image"
142+
},
143+
"pan_analytic": {
144+
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
145+
"roles": [
146+
"data"
147+
],
148+
"title": "Panchromatic Image"
149+
}
150+
},
151+
"stac_version": "1.0.0",
152+
"stac_extensions": [
153+
"https://stac-extensions.github.io/item-assets/v1.0.0/schema.json",
154+
"https://stac-extensions.github.io/render/v1.0.0/schema.json"
155+
]
156+
}
157+
],
158+
"links": [
159+
{
160+
"rel": "root",
161+
"type": "application/json",
162+
"href": "https://stac.endpoint.io/"
163+
},
164+
{
165+
"rel": "parent",
166+
"type": "application/json",
167+
"href": "https://stac.endpoint.io/"
168+
},
169+
{
170+
"rel": "self",
171+
"type": "application/json",
172+
"href": "https://stac.endpoint.io/collections"
173+
}
174+
]
175+
}

tests/test_render.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""test render extension."""
2+
3+
import json
4+
import os
5+
from unittest.mock import patch
6+
7+
import pystac
8+
9+
from titiler.core import dependencies
10+
from titiler.stacapi.factory import get_dependency_params, get_layer_from_collections
11+
12+
catalog_json = os.path.join(os.path.dirname(__file__), "fixtures", "catalog.json")
13+
14+
15+
@patch("titiler.stacapi.factory.Client")
16+
def test_render(client):
17+
"""test STAC items endpoints."""
18+
19+
with open(catalog_json, "r") as f:
20+
collections = [
21+
pystac.Collection.from_dict(c) for c in json.loads(f.read())["collections"]
22+
]
23+
client.open.return_value.get_collections.return_value = collections
24+
25+
collections_render = get_layer_from_collections(
26+
"https://something.stac", None, None
27+
)
28+
assert len(collections_render) == 3
29+
30+
visual = collections_render["MAXAR_BayofBengal_Cyclone_Mocha_May_23_visual"]
31+
assert visual["bbox"]
32+
assert visual["tilematrixsets"]["WebMercatorQuad"]
33+
assert visual["time"]
34+
assert visual["render"]["asset_bidx"]
35+
36+
color = collections_render["MAXAR_BayofBengal_Cyclone_Mocha_May_23_color"]["render"]
37+
assert isinstance(color["colormap"], str)
38+
39+
cmap = get_dependency_params(
40+
dependency=dependencies.ColorMapParams,
41+
query_params=color,
42+
)
43+
assert cmap
44+
45+
visualr = collections_render["MAXAR_BayofBengal_Cyclone_Mocha_May_23_visualr"][
46+
"render"
47+
]
48+
assert isinstance(visualr["rescale"][0], str)
49+
rescale = get_dependency_params(
50+
dependency=dependencies.RescalingParams,
51+
query_params=visualr,
52+
)
53+
assert rescale

titiler/stacapi/factory.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ class WMTSMediaType(str, Enum):
552552
TTLCache(maxsize=cache_config.maxsize, ttl=cache_config.ttl),
553553
key=lambda url, headers, supported_tms: hashkey(url, json.dumps(headers)),
554554
)
555-
def get_layer_from_collections(
555+
def get_layer_from_collections( # noqa: C901
556556
url: str,
557557
headers: Optional[Dict] = None,
558558
supported_tms: Optional[TileMatrixSets] = None,
@@ -647,9 +647,29 @@ def get_layer_from_collections(
647647
for x in range(0, (end_date - start_date).days + 1)
648648
]
649649

650-
# TODO:
651-
# special encoding for ColorMaps
652650
render = layer["render"] or {}
651+
652+
# special encoding for rescale
653+
# Per Specification, the rescale entry is a 2d array in form of `[[min, max], [min,max]]`
654+
# We need to convert this to `['{min},{max}', '{min},{max}']` for titiler dependency
655+
if rescale := render.pop("rescale", None):
656+
rescales = []
657+
for r in rescale:
658+
if not isinstance(r, str):
659+
rescales.append(",".join(map(str, r)))
660+
else:
661+
rescales.append(r)
662+
663+
render["rescale"] = rescales
664+
665+
# special encoding for ColorMaps
666+
# Per Specification, the colormap is a JSON object. TiTiler dependency expects a string encoded dict
667+
if colormap := render.pop("colormap", None):
668+
if not isinstance(colormap, str):
669+
colormap = json.dumps(colormap)
670+
671+
render["colormap"] = colormap
672+
653673
qs = urlencode(
654674
[(k, v) for k, v in render.items() if v is not None],
655675
doseq=True,
@@ -810,19 +830,11 @@ def get_tile( # noqa: C901
810830
):
811831
image = post_process(image)
812832

813-
if "rescale" in query_params:
814-
rescales = []
815-
for r in query_params["rescale"]:
816-
if not isinstance(r, str):
817-
rescales.append(",".join(map(str, r)))
818-
else:
819-
rescales.append(r)
820-
821-
if rescale := get_dependency_params(
822-
dependency=self.rescale_dependency,
823-
query_params={"rescale": rescales},
824-
):
825-
image.rescale(rescale)
833+
if rescale := get_dependency_params(
834+
dependency=self.rescale_dependency,
835+
query_params=query_params,
836+
):
837+
image.rescale(rescale)
826838

827839
if color_formula := get_dependency_params(
828840
dependency=self.color_formula_dependency,

0 commit comments

Comments
 (0)