Skip to content

Dynamic creation of related style definitions for OWS #549

@valpesendorfer

Description

@valpesendorfer

We've been recently running into issues creating related style definitions for WMS layers served out of the ODC, where one style definition would work, and an identical one with few changes would throw an error.

After a discussion in Slack, the solution was to create a deep copy and modify the elements needed for the new style. There are a couple of examples here in this repo.

I thought this is a bit cumbersome and not practical if you need many definitions which are related, so I've created a little function wrapper to take care of this. In the slack discussion I've been asked to share it in this issue:

import copy

def copy_style(template, **kwargs):

    tem_copy = copy.deepcopy(template)

    for name, value in kwargs.items():
        try:
            if name == 'bands':

                if isinstance(value, list):
                    tem_copy['needed_bands'] = value
                    tem_copy['index_function']['kwargs'] = {f'band{ix+1}':band for ix, band in enumerate(value)}
                else:
                    tem_copy['needed_bands'] = [value]
                    tem_copy['index_function']['kwargs']['band'] = value
            else:
                tem_copy[name] = value

        except KeyError:
            raise ValueError(f'Could not assign {name} to style!')

    return tem_copy

Basically, the keywords are a 1:1 match, with the exception of bands, so multiple bands can be specified.

So, if you have a template like this:

style_template_singleband = {
    "name": "name",
    "title": "title",
    "abstract": "Abstract",
    "needed_bands": ["data"],
    "index_function": {
        "function": "datacube_ows.band_utils.single_band",
        "pass_product_cfg": True,
        "kwargs": {
            "band": "data",
        }
    },
    "color_ramp": [],
    "legend": {
        "title": "Legend Ttile",
        "radix_point": 0,
        "scale_by": 1,
        "major_ticks": 20,
        "units": "unitless"
    }
}

You can create a new style like

style_s1p = copy_style(
    template=style_template_singleband,
    name='s1p',
    title='SPI 1 Month',
    abstract='Standard Precipitation Index over 1 Month',
    bands='s1p',
    color_ramp=spi_color_ramp,
    )

Which then can be a template to a more closely related style.


Disclaimer:

I'm not a professional python programmer, and this function was created to mainly deal with the single band definitions that we use at the moment. I know this won't work with the multiband ones, and also it won't be able to replace nested elements aside the ones related to band.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions