Skip to content

Commit 5158f9d

Browse files
refactor render dependencies (#1029)
* refactor render dependencies * fix
1 parent 98a417d commit 5158f9d

File tree

11 files changed

+169
-159
lines changed

11 files changed

+169
-159
lines changed

CHANGES.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,25 @@
88
* improve query string handling in LowerCaseQueryStringMiddleware using urlencode (author @pratapvardhan, https://github.com/developmentseed/titiler/pull/1050)
99
* add `titiler.core.utils.bounds_to_geometry` and reduce code duplication in factories (author @PratapVardhan, https://github.com/developmentseed/titiler/pull/1047)
1010
* simplify image format dtype validation in `render_image` (author @PratapVardhan, https://github.com/developmentseed/titiler/pull/1046)
11+
* remove `rescale_dependency` and `color_formula_dependency` attributes in `TilerFactory` class **breaking change**
12+
* move `rescale` and `color_formula` QueryParameters dependencies in `ImageRenderingParams` class **breaking change**
13+
* handle image rescaling and color_formula within `titiler.core.utils.render_image` function **breaking change**
14+
* add `render_func: Callable[..., Tuple[bytes, str]] = render_image` attribute in `TilerFactory` class
1115

1216
### titiler.application
1317

1418
* update `/healthz` endpoint to return dependencies versions (titiler, rasterio, gdal, ...) (author @scottyhq, https://github.com/developmentseed/titiler/pull/1056)
1519
* migrate `templates/index.html` to bootstrap5, remove unused css, reuse bs classes (author @PratapVardhan, https://github.com/developmentseed/titiler/pull/1048)
1620

21+
### titiler.mosaic
22+
23+
* remove `rescale_dependency` and `color_formula_dependency` attributes in `MosaicTilerFactory` class **breaking change**
24+
* add `render_func: Callable[..., Tuple[bytes, str]] = render_image` attribute in `MosaicTilerFactory` class **breaking change**
25+
26+
### titiler.extensions
27+
28+
* use `factory.render_func` as render function in `wmsExtension` endpoints
29+
1730
### Misc
1831

1932
* Updated WMTS Capabilities template to avoid inserting extra new lines (author @AndrewAnnex, https://github.com/developmentseed/titiler/pull/1052).

docs/src/advanced/dependencies.md

Lines changed: 42 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -412,32 +412,6 @@ class BidxExprParams(ExpressionParams, BidxParams):
412412

413413
</details>
414414

415-
#### `ColorFormulaParams`
416-
417-
Color Formula option (see https://github.com/vincentsarago/color-operations).
418-
419-
| Name | Type | Required | Default
420-
| ------ | ----------|----------|--------------
421-
| **color_formula** | Query (str) | No | None
422-
423-
<details>
424-
425-
```python
426-
def ColorFormulaParams(
427-
color_formula: Annotated[
428-
Optional[str],
429-
Query(
430-
title="Color Formula",
431-
description="rio-color formula (info: https://github.com/mapbox/rio-color)",
432-
),
433-
] = None,
434-
) -> Optional[str]:
435-
"""ColorFormula Parameter."""
436-
return color_formula
437-
```
438-
439-
</details>
440-
441415
#### `ColorMapParams`
442416

443417
Colormap options. See [titiler.core.dependencies](https://github.com/developmentseed/titiler/blob/e46c35c8927b207f08443a274544901eb9ef3914/src/titiler/core/titiler/core/dependencies.py#L18-L54).
@@ -709,9 +683,11 @@ link: https://numpy.org/doc/stable/reference/generated/numpy.histogram.html
709683

710684
Control output image rendering options.
711685

712-
| Name | Type | Required | Default
713-
| ------ | ----------|----------|--------------
714-
| **return_mask** | Query (bool) | No | False
686+
| Name | Type | Required | Default
687+
| ------ | ---------- |----------|--------------
688+
| **rescale** | Query (str, comma delimited Numer) | No | None
689+
| **color_formula** | Query (str) | No | None
690+
| **return_mask** | Query (bool) | No | False
715691

716692
<details>
717693

@@ -720,13 +696,49 @@ Control output image rendering options.
720696
class ImageRenderingParams(DefaultDependency):
721697
"""Image Rendering options."""
722698

699+
rescale: Annotated[
700+
Optional[List[str]],
701+
Query(
702+
title="Min/Max data Rescaling",
703+
description="comma (',') delimited Min,Max range. Can set multiple time for multiple bands.",
704+
examples=["0,2000", "0,1000", "0,10000"], # band 1 # band 2 # band 3
705+
),
706+
] = None
707+
708+
color_formula: Annotated[
709+
Optional[str],
710+
Query(
711+
title="Color Formula",
712+
description="rio-color formula (info: https://github.com/mapbox/rio-color)",
713+
),
714+
] = None
715+
723716
add_mask: Annotated[
724717
Optional[bool],
725718
Query(
726719
alias="return_mask",
727-
description="Add mask to the output data. Defaults to `True` in rio-tiler",
720+
description="Add mask to the output data. Defaults to `True`",
728721
),
729722
] = None
723+
724+
def __post_init__(self):
725+
"""Post Init."""
726+
if self.rescale:
727+
rescale_array = []
728+
for r in self.rescale:
729+
parsed = tuple(
730+
map(
731+
float,
732+
r.replace(" ", "").replace("[", "").replace("]", "").split(","),
733+
)
734+
)
735+
assert (
736+
len(parsed) == 2
737+
), f"Invalid rescale values: {self.rescale}, should be of form ['min,max', 'min,max'] or [[min,max], [min, max]]"
738+
rescale_array.append(parsed)
739+
740+
self.rescale: RescaleType = rescale_array # Noqa
741+
730742
```
731743

732744
</details>
@@ -815,36 +827,6 @@ class PreviewParams(DefaultDependency):
815827

816828
</details>
817829

818-
#### `RescalingParams`
819-
820-
Set Min/Max values to rescale from, to 0 -> 255.
821-
822-
| Name | Type | Required | Default
823-
| ------ | ----------|----------|--------------
824-
| **rescale** | Query (str, comma delimited Numer) | No | None
825-
826-
<details>
827-
828-
```python
829-
def RescalingParams(
830-
rescale: Annotated[
831-
Optional[List[str]],
832-
Query(
833-
title="Min/Max data Rescaling",
834-
description="comma (',') delimited Min,Max range. Can set multiple time for multiple bands.",
835-
examples=["0,2000", "0,1000", "0,10000"], # band 1 # band 2 # band 3
836-
),
837-
] = None,
838-
) -> Optional[RescaleType]:
839-
"""Min/Max data Rescaling"""
840-
if rescale:
841-
return [tuple(map(float, r.replace(" ", "").split(","))) for r in rescale]
842-
843-
return None
844-
```
845-
846-
</details>
847-
848830
#### StatisticsParams
849831

850832
Define options for *rio-tiler*'s statistics method.

docs/src/advanced/endpoints_factories.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,12 @@ Factory meant to create endpoints for single dataset using [*rio-tiler*'s `Reade
4747
- **img_preview_dependency**: Dependency to define image size for `/preview` and `/statistics` endpoints. Defaults to `titiler.core.dependencies.PreviewParams`.
4848
- **img_part_dependency**: Dependency to define image size for `/bbox` and `/feature` endpoints. Defaults to `titiler.core.dependencies.PartFeatureParams`.
4949
- **process_dependency**: Dependency to control which `algorithm` to apply to the data. Defaults to `titiler.core.algorithm.algorithms.dependency`.
50-
- **rescale_dependency**: Dependency to set Min/Max values to rescale from, to 0 -> 255. Defaults to `titiler.core.dependencies.RescalingParams`.
51-
- **color_formula_dependency**: Dependency to define the Color Formula. Defaults to `titiler.core.dependencies.ColorFormulaParams`.
5250
- **colormap_dependency**: Dependency to define the Colormap options. Defaults to `titiler.core.dependencies.ColorMapParams`
5351
- **render_dependency**: Dependency to control output image rendering options. Defaults to `titiler.core.dependencies.ImageRenderingParams`
5452
- **environment_dependency**: Dependency to define GDAL environment at runtime. Default to `lambda: {}`.
5553
- **supported_tms**: List of available TileMatrixSets. Defaults to `morecantile.tms`.
5654
- **templates**: *Jinja2* templates to use in endpoints. Defaults to `titiler.core.factory.DEFAULT_TEMPLATES`.
55+
- **render_func**: Image rendering method. Defaults to `titiler.core.utils.render_image`.
5756
- **add_preview**: . Add `/preview` endpoint to the router. Defaults to `True`.
5857
- **add_part**: . Add `/bbox` and `/feature` endpoints to the router. Defaults to `True`.
5958
- **add_viewer**: . Add `/map` endpoints to the router. Defaults to `True`.
@@ -304,8 +303,6 @@ Endpoints factory for mosaics, built on top of [MosaicJSON](https://github.com/d
304303
- **dataset_dependency**: Dependency to overwrite `nodata` value, apply `rescaling` and change the `I/O` or `Warp` resamplings. Defaults to `titiler.core.dependencies.DatasetParams`.
305304
- **tile_dependency**: Dependency to define `buffer` and `padding` to apply at tile creation. Defaults to `titiler.core.dependencies.TileParams`.
306305
- **process_dependency**: Dependency to control which `algorithm` to apply to the data. Defaults to `titiler.core.algorithm.algorithms.dependency`.
307-
- **rescale_dependency**: Dependency to set Min/Max values to rescale from, to 0 -> 255. Defaults to `titiler.core.dependencies.RescalingParams`.
308-
- **color_formula_dependency**: Dependency to define the Color Formula. Defaults to `titiler.core.dependencies.ColorFormulaParams`.
309306
- **colormap_dependency**: Dependency to define the Colormap options. Defaults to `titiler.core.dependencies.ColorMapParams`
310307
- **render_dependency**: Dependency to control output image rendering options. Defaults to `titiler.core.dependencies.ImageRenderingParams`
311308
- **pixel_selection_dependency**: Dependency to select the `pixel_selection` method. Defaults to `titiler.mosaic.factory.PixelSelectionParams`.
@@ -353,8 +350,6 @@ class: `titiler.xarray.factory.TilerFactory`
353350
- **histogram_dependency**: Dependency to define *numpy*'s histogram options used in `/statistics` endpoints. Defaults to `titiler.core.dependencies.HistogramParams`.
354351
- **img_part_dependency**: Dependency to define image size for `/bbox` and `/feature` endpoints. Defaults to `titiler.xarray.dependencies.PartFeatureParams`.
355352
- **process_dependency**: Dependency to control which `algorithm` to apply to the data. Defaults to `titiler.core.algorithm.algorithms.dependency`.
356-
- **rescale_dependency**: Dependency to set Min/Max values to rescale from, to 0 -> 255. Defaults to `titiler.core.dependencies.RescalingParams`.
357-
- **color_formula_dependency**: Dependency to define the Color Formula. Defaults to `titiler.core.dependencies.ColorFormulaParams`.
358353
- **colormap_dependency**: Dependency to define the Colormap options. Defaults to `titiler.core.dependencies.ColorMapParams`
359354
- **render_dependency**: Dependency to control output image rendering options. Defaults to `titiler.core.dependencies.ImageRenderingParams`
360355
- **environment_dependency**: Dependency to define GDAL environment at runtime. Default to `lambda: {}`.

src/titiler/core/tests/test_CustomRender.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class CustomRenderParams(ImageRenderingParams):
3030

3131
def __post_init__(self):
3232
"""post init."""
33+
super().__post_init__()
3334
if self.nodata is not None:
3435
self.nodata = numpy.nan if self.nodata == "nan" else float(self.nodata)
3536

src/titiler/core/tests/test_dependencies.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,9 +500,9 @@ def test_rescale_params():
500500
app = FastAPI()
501501

502502
@app.get("/")
503-
def main(rescale=Depends(dependencies.RescalingParams)):
503+
def main(params=Depends(dependencies.ImageRenderingParams)):
504504
"""return rescale."""
505-
return rescale
505+
return params.rescale
506506

507507
client = TestClient(app)
508508

src/titiler/core/tests/test_factories.py

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import pathlib
66
import warnings
77
import xml.etree.ElementTree as ET
8+
from dataclasses import dataclass
89
from enum import Enum
910
from io import BytesIO
1011
from typing import Dict, Optional, Sequence, Type
@@ -26,8 +27,9 @@
2627
from rio_tiler.io import BaseReader, MultiBandReader, Reader, STACReader
2728
from starlette.requests import Request
2829
from starlette.testclient import TestClient
30+
from typing_extensions import Annotated
2931

30-
from titiler.core.dependencies import RescaleType
32+
from titiler.core import dependencies
3133
from titiler.core.errors import DEFAULT_STATUS_CODES, add_exception_handlers
3234
from titiler.core.factory import (
3335
AlgorithmFactory,
@@ -1757,11 +1759,34 @@ def test_AutoFormat_Colormap():
17571759
def test_rescale_dependency():
17581760
"""Ensure that we can set default rescale values via the rescale_dependency"""
17591761

1760-
def custom_rescale_params() -> Optional[RescaleType]:
1761-
return [(0, 100)]
1762+
@dataclass
1763+
class ImageRenderingParams(dependencies.ImageRenderingParams):
1764+
"""Custom ImageParams."""
1765+
1766+
def __post_init__(self):
1767+
if self.rescale:
1768+
rescale_array = []
1769+
for r in self.rescale:
1770+
parsed = tuple(
1771+
map(
1772+
float,
1773+
r.replace(" ", "")
1774+
.replace("[", "")
1775+
.replace("]", "")
1776+
.split(","),
1777+
)
1778+
)
1779+
assert (
1780+
len(parsed) == 2
1781+
), f"Invalid rescale values: {self.rescale}, should be of form ['min,max', 'min,max'] or [[min,max], [min, max]]"
1782+
rescale_array.append(parsed)
1783+
1784+
self.rescale = rescale_array # Noqa
1785+
else:
1786+
self.rescale = [(0, 100)]
17621787

17631788
cog = TilerFactory()
1764-
cog_custom_range = TilerFactory(rescale_dependency=custom_rescale_params)
1789+
cog_custom_range = TilerFactory(render_dependency=ImageRenderingParams)
17651790

17661791
app = FastAPI()
17671792
app.include_router(cog.router, prefix="/cog")
@@ -1839,13 +1864,20 @@ def test_dst_crs_option():
18391864
def test_color_formula_dependency():
18401865
"""Ensure that we can set default color formulae via the color_formula_dependency"""
18411866

1842-
def custom_color_formula_params() -> Optional[str]:
1843-
return "sigmoidal R 7 0.4"
1867+
@dataclass
1868+
class ImageRenderingParams(dependencies.ImageRenderingParams):
1869+
"""Custom ImageParams."""
1870+
1871+
color_formula: Annotated[
1872+
Optional[str],
1873+
Query(
1874+
title="Color Formula",
1875+
description="rio-color formula (info: https://github.com/mapbox/rio-color)",
1876+
),
1877+
] = "sigmoidal R 7 0.4"
18441878

18451879
cog = TilerFactory()
1846-
cog_custom_color_formula = TilerFactory(
1847-
color_formula_dependency=custom_color_formula_params
1848-
)
1880+
cog_custom_color_formula = TilerFactory(render_dependency=ImageRenderingParams)
18491881

18501882
app = FastAPI()
18511883
app.include_router(cog.router, prefix="/cog")

src/titiler/core/titiler/core/dependencies.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,10 +425,30 @@ def __post_init__(self):
425425
self.unscale = bool(self.unscale)
426426

427427

428+
RescaleType = List[Tuple[float, float]]
429+
430+
428431
@dataclass
429432
class ImageRenderingParams(DefaultDependency):
430433
"""Image Rendering options."""
431434

435+
rescale: Annotated[
436+
Optional[List[str]],
437+
Query(
438+
title="Min/Max data Rescaling",
439+
description="comma (',') delimited Min,Max range. Can set multiple time for multiple bands.",
440+
examples=["0,2000", "0,1000", "0,10000"], # band 1 # band 2 # band 3
441+
),
442+
] = None
443+
444+
color_formula: Annotated[
445+
Optional[str],
446+
Query(
447+
title="Color Formula",
448+
description="rio-color formula (info: https://github.com/mapbox/rio-color)",
449+
),
450+
] = None
451+
432452
add_mask: Annotated[
433453
Optional[bool],
434454
Query(
@@ -437,8 +457,23 @@ class ImageRenderingParams(DefaultDependency):
437457
),
438458
] = None
439459

460+
def __post_init__(self):
461+
"""Post Init."""
462+
if self.rescale:
463+
rescale_array = []
464+
for r in self.rescale:
465+
parsed = tuple(
466+
map(
467+
float,
468+
r.replace(" ", "").replace("[", "").replace("]", "").split(","),
469+
)
470+
)
471+
assert (
472+
len(parsed) == 2
473+
), f"Invalid rescale values: {self.rescale}, should be of form ['min,max', 'min,max'] or [[min,max], [min, max]]"
474+
rescale_array.append(parsed)
440475

441-
RescaleType = List[Tuple[float, float]]
476+
self.rescale: RescaleType = rescale_array
442477

443478

444479
def RescalingParams(
@@ -452,6 +487,11 @@ def RescalingParams(
452487
] = None,
453488
) -> Optional[RescaleType]:
454489
"""Min/Max data Rescaling"""
490+
warnings.warn(
491+
"RescalingParams is deprecated and set to be removed in 0.20",
492+
DeprecationWarning,
493+
stacklevel=1,
494+
)
455495
if rescale:
456496
rescale_array = []
457497
for r in rescale:
@@ -646,6 +686,11 @@ def ColorFormulaParams(
646686
] = None,
647687
) -> Optional[str]:
648688
"""ColorFormula Parameter."""
689+
warnings.warn(
690+
"ColorFormulaParams is deprecated and set to be removed in 0.20",
691+
DeprecationWarning,
692+
stacklevel=1,
693+
)
649694
return color_formula
650695

651696

0 commit comments

Comments
 (0)