Skip to content

Commit

Permalink
multi-date handler aggregator in ramp styles can now receive raw data (
Browse files Browse the repository at this point in the history
…#1033)

* First attempt to implement raw data passing.

* Fix intermediate array dtype for numpy2

* Basic test.

* Wordlist update.

* Wordlist update.
  • Loading branch information
SpacemanPaul authored Jul 16, 2024
1 parent bca8a8e commit 41daa21
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 20 deletions.
11 changes: 11 additions & 0 deletions datacube_ows/band_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,17 @@ def multi_date_delta(data, time_direction=-1):
def multi_date_pass(data):
return data

def multi_date_raw_example(data, band1, band2, band_mapper=None):
if band_mapper:
band1 = band_mapper(band1)
band2 = band_mapper(band2)
data1, data2 = (data.sel(time=dt) for dt in data.coords["time"].values)
return (
(data2[band1] - data1[band1]) - (data2[band2] - data1[band2])
) / (
data1[band1] + data1[band2] + data2[band1] + data2[band2]
)


@band_modulator
@scalable
Expand Down
2 changes: 1 addition & 1 deletion datacube_ows/styles/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def transform_single_date_data(self, data: "xarray.Dataset") -> "xarray.Dataset"
else:
imgband_data = imgband_component
if imgband_data is None:
null_np = np.zeros(list(data.dims.values()), 'uint8')
null_np = np.zeros(list(data.dims.values()), 'float64')
imgband_data = DataArray(null_np, data.coords, data.dims.keys())
if imgband != "alpha":
imgband_data = self.compress_band(imgband, imgband_data)
Expand Down
10 changes: 8 additions & 2 deletions datacube_ows/styles/ramp.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,9 +574,11 @@ def __init__(self, style: "ColorRampDef", cfg: CFG_DICT) -> None:
if self.animate:
self.feature_info_label: Optional[str] = None
self.color_ramp = style.color_ramp
self.pass_raw_data = False
else:
self.feature_info_label = cast(Optional[str], cfg.get("feature_info_label", None))
self.color_ramp = ColorRamp(style, cfg, self.legend_cfg)
self.pass_raw_data = bool(cfg.get("pass_raw_data", False))

def transform_data(self, data: "xarray.Dataset") -> "xarray.Dataset":
"""
Expand All @@ -585,13 +587,17 @@ def transform_data(self, data: "xarray.Dataset") -> "xarray.Dataset":
:param data: Raw data
:return: RGBA image xarray. May have a time dimension
"""
xformed_data = cast("ColorRampDef", self.style).apply_index(data)
agg = self.aggregator(xformed_data)
if self.pass_raw_data:
agg = self.aggregator(data)
else:
xformed_data = cast("ColorRampDef", self.style).apply_index(data)
agg = self.aggregator(xformed_data)
return self.color_ramp.apply(agg)

class Legend(RampLegendBase):
def plot_name(self):
return f"{self.style.product.name}_{self.style.name}_{self.style_or_mdh.min_count}"


# Register ColorRampDef as Style subclass.
StyleDefBase.register_subclass(ColorRampDef, ("range", "color_ramp"))
44 changes: 28 additions & 16 deletions docs/cfg_colourramp_styles.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ entry.
index_function
++++++++++++++

The `index_function` allows the user to declare a callback function
The ``index_function`` allows the user to declare a callback function
to calculate the index value using OWS's
`function configuration format <https://datacube-ows.readthedocs.io/en/latest/cfg_functions.html>`_.
The function is expected to take an xarray Dataset containing all the
Expand All @@ -76,12 +76,12 @@ an xarray Dataset containing the index value.

A `small library <https://datacube-ows.readthedocs.io/en/latest/cfg_functions.html#band-utils-functions>`_
of general purpose band math functions
are provided in `datacube_ows.band_utils`.
are provided in ``datacube_ows.band_utils``.

needed_bands list
+++++++++++++++++

The `needed_bands` entry must list the names (or aliases) of
The ``needed_bands`` entry must list the names (or aliases) of
all the bands required by the
`index_function <#index-function>`__.

Expand Down Expand Up @@ -125,7 +125,7 @@ Ramp Scale (Range)
==================

For the Matplotlib colour ramps and the default colour ramp, you need to specify
a value range over which the colour ramp is applied. The `range` element can be set
a value range over which the colour ramp is applied. The ``range`` element can be set
to a tuple containing the index function values that should be mapped to the lowest
and highest colour ramp values.

Expand Down Expand Up @@ -154,8 +154,8 @@ E.g.::
Manual color_ramp
=================

A colour ramp can be created manually using the `color_ramp` style configuration
entry. `color_ramp` should be a list of `colour point definitions <#colour-point-definition>`_.
A colour ramp can be created manually using the ``color_ramp`` style configuration
entry. ``color_ramp`` should be a list of `colour point definitions <#colour-point-definition>`_.
Each colour point definition describes a mapping from a value to a colour.

The list should be sorted in order of ascending value. If the index function value
Expand Down Expand Up @@ -218,9 +218,9 @@ Legend Configuration
Colour-ramp styles support automatic legend generation.

Automatic legend generation can be deactivated using the
`show_legend` and `url` legend elements
``show_legend`` and ``url`` legend elements
`common to all styles <https://datacube-ows.readthedocs.io/en/latest/cfg_styling.html#legend>`_.
(`show_legend` is `True` by default for colour-ramp styles.)
(``show_legend`` is ``True`` by default for colour-ramp styles.)

Legend Title
============
Expand Down Expand Up @@ -421,7 +421,7 @@ Over-riding labels for individual ticks
+++++++++++++++++++++++++++++++++++++++

If a tick's default label (with no prefix or suffix) appears as a key
in the `tick_labels` dictionary then the prefix, suffix or label of
in the ``tick_labels`` dictionary then the prefix, suffix or label of
that tick label can be overridden.

E.g.::
Expand Down Expand Up @@ -474,7 +474,7 @@ further information.
Image Size
++++++++++

The `width` and `height` values are passed to matplotlib to specify the size
The ``width`` and ``height`` values are passed to matplotlib to specify the size
of the generated image.

The image size defaults to 4 inches wide by 1.25 inches tall. The default
Expand All @@ -492,7 +492,7 @@ strip_location
++++++++++++++

The location of the coloured ramp strip within the legend image can be
customised with the `strip_location` element. This should be a tuple
customised with the ``strip_location`` element. This should be a tuple
of four floats which is passed directly to the MatPlotLib Figure.add_axes
function.

Expand All @@ -512,7 +512,7 @@ MatPlotLib rc params
++++++++++++++++++++

Other MatPlotLib customisations (as they would appear in a .matplotlibrc file)
can be specified with the optional `rcParams` element, defaulting to {}, meaning
can be specified with the optional ``rcParams`` element, defaulting to {}, meaning
the MatPlotLib defaults for all options.

For a full list of possible options refer to
Expand All @@ -537,16 +537,28 @@ by providing for an aggregator function that converts the multi-date index data
into a dateless index, and apply either the style's colour ramp (i.e. the same
as the single-date case), or a separate colour ramp.

pass_raw_data
=============

The ``pass_raw_data`` entry controls what data is passed to the aggregator function:

``pass_raw_data == False`` (the default):
The aggregator function is passed a time-dimensioned DataArray containing the output
of the index function.

``pass_raw_data == True``:
The aggregator function is passed a time-dimensioned Dataset, containing all of the
declared needed bands.

aggregator_function
===================

The `aggregator_function` entry is required for colour ramp style
The ``aggregator_function`` entry is required for colour ramp style
multi-date handlers. It is a function defined using OWS's
`function configuration format <https://datacube-ows.readthedocs.io/en/latest/cfg_functions.html>`_.

The function is assumed to take a single xarray Dataset with a time dimension.
The value at each time slice is the output of the `index function <#index-function>`__
at that time. The function should return an xarray Dataset with no time
The first argument passed to the function depends on the value of the ``pass_raw_data``
element, as described above. The function should return an xarray DataArray with no time
dimension, containing the data used as an input to the
`multi-date handler's colour ramp <#multi-date-colour-ramps>`__.

Expand Down
8 changes: 7 additions & 1 deletion integration_tests/cfg/ows_test_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,8 +393,14 @@
"allowed_count_range": [2, 2],
"animate": False,
"preserve_user_date_order": True,
"pass_raw_data": True,
"aggregator_function": {
"function": "datacube_ows.band_utils.multi_date_delta",
"function": "datacube_ows.band_utils.multi_date_raw_example",
"mapped_bands": True,
"kwargs": {
"band1": "nir",
"band2": "red",
}
},
"mpl_ramp": "RdYlBu",
"range": [-1.0, 1.0],
Expand Down
8 changes: 8 additions & 0 deletions wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ audreyr
australia
auth
autogenerate
autoupdate
awk
aws
ba
Expand All @@ -51,6 +52,7 @@ bd
bda
beb
befce
benjimin
bfa
bitflag
bitflags
Expand Down Expand Up @@ -117,12 +119,14 @@ dde
de
dea
deafrica
dependabot
desc
describecoverage
DescribeCoverage
dev
df
digitalearthafrica
dimensioned
dir
dns
docstrings
Expand Down Expand Up @@ -158,6 +162,7 @@ fdb
fdba
fde
fe
FeatureInfo
featurelisturls
FeatureListURLs
fqn
Expand All @@ -166,6 +171,7 @@ func
gda
gdal
geobase
geojson
geomedian
geoscience
geoscienceaustralia
Expand All @@ -187,6 +193,7 @@ gettext
gettile
GetTile
gh
GHA
github
githubusercontent
googlemap
Expand Down Expand Up @@ -287,6 +294,7 @@ petrak
pgdata
pil
pindge
pjonsson
pki
png
po
Expand Down

0 comments on commit 41daa21

Please sign in to comment.