Skip to content

Conversation

vincentsarago
Copy link
Member

@vincentsarago vincentsarago commented Jul 7, 2022

This PR sketchs out support for complex algorithm (advanced expression)

TL&DR

we introduce the concept of the Algorithm base class

class BaseAlgorithm():
    """Algorithm baseclass."""

    input_nbands: int

    output_nbands: int
    output_dtype: str
    output_min: Optional[Sequence]
    output_max: Optional[Sequence]

    @abc.abstractmethod
    def apply(self, img: ImageData) -> ImageData:
        """Apply"""
        ...

The base class has some attribute used for metadata (what inputs It needs and what outputs it will produce).

which is then used to create custom algorithm with an apply method that takes an ImageData object as input and return another ImageData object (

rio-viz/rio_viz/app.py

Lines 306 to 307 in 68a6b6b

if postprocess_params.image_process:
img = postprocess_params.image_process.apply(img)
)

class HillShade(BaseAlgorithm):
    """Hillshade."""

    # User defined options
    azimuth: int = 90
    angle_altitude: float = 90

    # Algo metadata 
    input_nbands: int = 1
    output_nbands: int = 1
    output_dtype: str = "uint8"

    def apply(self, img: ImageData) -> ImageData:
        """Create hillshade from DEM dataset."""
        data = img.data[0]
        mask = img.mask

        x, y = numpy.gradient(data)

        slope = numpy.pi / 2.0 - numpy.arctan(numpy.sqrt(x * x + y * y))
        aspect = numpy.arctan2(-x, y)
        azimuthrad = self.azimuth * numpy.pi / 180.0
        altituderad = self.angle_altitude * numpy.pi / 180.0
        shaded = numpy.sin(altituderad) * numpy.sin(slope) + numpy.cos(
            altituderad
        ) * numpy.cos(slope) * numpy.cos(azimuthrad - aspect)
        hillshade_array = 255 * (shaded + 1) / 2

        # ImageData only accept image in form of (count, height, width)
        arr = numpy.expand_dims(hillshade_array, axis=0).astype(dtype=numpy.uint8)

        return ImageData(
            arr,
            mask,
            assets=img.assets,
            crs=img.crs,
            bounds=img.bounds,
        )

http://127.0.0.1:8080/preview?algo=contours&algo_params={"minz":1600,"maxz":2100,"increment":10}
preview

http://127.0.0.1:8080/preview?algo=hillshade&algo_params={"angle_altitude":20}
preview-1

output_nbands: int
output_dtype: str
output_min: Optional[Sequence]
output_max: Optional[Sequence]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are metadata about the input/outputs of the algorithm

tuple(map(float, r.replace(" ", "").split(","))) for r in self.rescale
]

kwargs = json.loads(self.algorithm_params) if self.algorithm_params else {}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

additional parameters for the algorithm must be provided as JSON encoded algo_params query parameter

@vincentsarago
Copy link
Member Author

TODO: add frontend support

@vincentsarago
Copy link
Member Author

This was integrated directly in TiTiler

@vincentsarago vincentsarago deleted the customAlgorithm branch December 16, 2022 10:10
@jo-chemla
Copy link

TODO: add frontend support

Frontend support for algorithms as well as custom expression added in PR to titiler /cog/viewer developmentseed/titiler#1119 for anyone interested

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants