developmentseed / titiler

Build your own Raster dynamic map tile services
https://developmentseed.org/titiler/
MIT License
765 stars 157 forks source link

Issues with colormaps #738

Closed delbronski closed 9 months ago

delbronski commented 9 months ago

Problem description

A have a tiff file of bioclimate zones. It is a simple 1 band tiff, Float32, min: 0.0, max:15.0. Each Float represents a bioclimate zone, so 0.0 represents Artic, 1 represents Extremely Cold and Wet, etc. So inside the tiff is just a big matrix from 0.0 to 15.0 each cell representing one of the zones.

I am trying to apply the following custom discrete colormap but it does not work:

{0: '#00ffff', 1: '#539791', 2: '#57c217', 3: '#5d45ff', 4: '#62d989', 5: '#8cff29', 6: '#966eff', 7: '#b3cf64', 8: '#d6829c', 9: '#e8aa6c', 10: '#ffe180', 11: '#ffb8b4', 12: '#ffff8c', 13: '#ffb4c4', 14: '#ff0000', 15: '#ffdada'}

I get the following error:

File "..../venv/lib/python3.11/site-packages/rio_tiler/colormap.py", line 114, in apply_cmap data = lookup_table[data[0], :]


IndexError: arrays used as indices must be of integer (or boolean) type

So I tried this:

[[[0, 1], '#00ffff'], [[1, 2], '#539791'], [[2, 3], '#57c217'], [[3, 4], '#5d45ff'], [[4, 5], '#62d989'], [[5, 6], '#8cff29'], [[6, 7], '#966eff'], [[7, 8], '#b3cf64'], [[8, 9], '#d6829c'], [[9, 10], '#e8aa6c'], [[10, 11], '#ffe180'], [[11, 12], '#ffb8b4'], [[12, 13], '#ffff8c'], [[13, 14], '#ffb4c4'], [[14, 15], '#ff0000'], [[15, 16], '#ffdada']]

and it works as expected. 

However, I am confused because I would expect my first example to work as a discrete colormap. I saw this line in colormap.py:

    if len(colormap) > 256 or max(colormap) >= 256 or min(colormap) < 0:
        return apply_discrete_cmap(data, colormap)

Maybe apply_discrete_cmap is what I am looking for...But I am not sure if I understand correctly. Does this mean that unless the length of the colormap is > 256   or one of the values is >256/< 0, then we cannot apply a discrete colormap? What if I want to make a custom discrete colormap that is only 15 categories? Must we declare that as an interval colormap? If so, then that does not make a lot of sense to me. 

#### Expected Output

I would expect that this custom colormap 

{0: '#00ffff', 1: '#539791', 2: '#57c217', 3: '#5d45ff', 4: '#62d989', 5: '#8cff29', 6: '#966eff', 7: '#b3cf64', 8: '#d6829c', 9: '#e8aa6c', 10: '#ffe180', 11: '#ffb8b4', 12: '#ffff8c', 13: '#ffb4c4', 14: '#ff0000', 15: '#ffdada'}

would work. Maybe we can pass a parameter to apply_cmap that allows the user to manually decide wether the colormap should be discrete or not? 

If I am misunderstanding something please let me know. Thanks for this amazing library and all the work you are doing! 
vincentsarago commented 9 months ago

🤔 I think it's a rio-tiler bug

if len(colormap) > 256 or max(colormap) >= 256 or min(colormap) < 0:
    return apply_discrete_cmap(data, colormap)

should be

if len(colormap) != 256 or max(colormap) >= 256 or min(colormap) < 0:
    return apply_discrete_cmap(data, colormap)
delbronski commented 9 months ago

Oh sorry I did not notice that file was part of the rio-tiler library. I think you are right! Thanks. I'll open a bug ticket on their repo then.

vincentsarago commented 9 months ago

no need, PR is already open and patch soon to be released :D

delbronski commented 9 months ago

no need, PR is already open and patch soon to be released :D

Thanks vincent!