# DynamicMap colorbar ticks will not update when parameter changes

**URL:** <https://discourse.holoviz.org/t/dynamicmap-colorbar-ticks-will-not-update-when-parameter-changes/8591>\
**Category:** HoloViews\
**Tags:** param, bokeh, panel, holoviews, dynamicmap\
**Created:** [February 18, 2025, 7:07pm UTC](https://discourse.holoviz.org/t/dynamicmap-colorbar-ticks-will-not-update-when-parameter-changes/8591 "2025-02-18T19:07:22Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![lee1](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/lee1/32/7133_2.png) [@lee1](https://discourse.holoviz.org/u/lee1)\
**Post date:** [February 18, 2025, 7:07pm UTC](https://discourse.holoviz.org/t/dynamicmap-colorbar-ticks-will-not-update-when-parameter-changes/8591/1 "2025-02-18T19:07:22Z")

</div>

We have a Panel app that has two linked DynamicMaps that have gridded data with point observation data overlayed. The data has 3 different output fields from the model (severity, probability, and SLD) and we have a parameter to cycle between these. We’ve also defined the colors, tick labels, and ticks for the colorbar for each field. However, when we run the app, all of the fields change appropriately and the colorbar changes to have the correct colors, but it will not change the ticks or tick labels.

COLORS = {  
“Severity”: [“#FFFFFF”, “#CCFFFF”, “#98CCFF”, “#6699FE”, “#3333FE”],  
“Probability”: [  
“#FFFFFF”,  
“#CCFFFF”,  
“#99FFCC”,  
“#99FF66”,  
“#CCFF66”,  
“#FFFF00”,  
“#FFCC00”,  
“#FF9900”,  
“#FF6600”,  
],  
“SLD”: [“#FFFFFF”, “#FFA500”, “#FF0000”],  
}  
BOUNDS = {  
“Severity”: [0, 1, 2, 3, 4, 5],  
“Probability”: [0.0, 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 1.0],  
“SLD”: [0.0, 0.05, 0.25, 1.0],  
}  
CLIMS = {  
“Severity”: (0, 5),  
“Probability”: (0, 1),  
“SLD”: (0, 1),  
}  
CTICKS = {  
“Severity”: [0.5, 1.5, 2.5, 3.5, 4.5],  
“Probability”: [0, 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 1],  
“SLD”: [0, 0.05, 0.25, 1],  
}

field = param.ObjectSelector(  
default=“Severity”, objects=[“Severity”, “Probability”, “SLD”]  
)  
lead = param.ObjectSelector(default=3, objects=[3, 6, 9, 12, 15, 18])  
map\_time = param.Selector(default=datetime.datetime(2024, 10, 28, 21))  
level = param.Selector(  
default=6000, objects=list(np.arange(1000, 31000, 1000, dtype=int))  
)  
deps = [“field”, “lead”, “map\_time”, “level”]

```
def __init__ (self, **params):
    """
    View product fields
    """
    super(). __init__ (**params)
    # self.colorbar_opts = self.get_colorbar_opts()
    self.plot = self.create_plot()
def get_colorbar_opts(self):
    """Dynamically generate colorbar options based on selected field."""
    field = self.field
    ct = CTICKS[field]

    if field == "Severity":
        ticks = [
            (0.5, "No Icing"),
            (1.5, "Trace"),
            (2.5, "Light"),
            (3.5, "Moderate"),
            (4.5, "Heavy"),
        ]
        print(ticks)
        return ticks
        # return {
        # "major_label_overrides": {
        # 0.5: "No Icing",
        # 1.5: "Trace",
        # 2.5: "Light",
        # 3.5: "Moderate",
        # 4.5: "Heavy",
        # },
        # "ticker": FixedTicker(ticks=ct),
        # }
    else:
        ticks = [(tick, f"{tick}") for tick in ct]
        print(ticks)
        return ticks
        # return {
        # "major_label_overrides": {tick: f"{tick}" for tick in ct},
        # "ticker": FixedTicker(ticks=ct),
        # }

@param.depends(*deps, watch=True)
def dynamic_plot(self):
    """
    The mapping function for the dynamic plots.
    """

    def plot_limits(plot):
        """
        plot limits
        """
        plot.handles["x_range"].min_interval = 10
        plot.handles["x_range"].max_interval = 1299
        plot.handles["y_range"].min_interval = 10
        plot.handles["y_range"].max_interval = 919

    valid = self.map_time
    level = self.level
    field = self.field
    lead = self.lead
    ds1, ds2 = self.prepare_data(field, lead)

    colorbar_opts = self.get_colorbar_opts()

    img1 = hv.Image(ds1).opts(hv.opts.Image(aspect="equal"))
    img1.opts(
        width=WIDTH,
        cmap=COLORS[field],
        color_levels=BOUNDS[field],
        clim=CLIMS[field],
        colorbar=True,
        # cticks=colorbar_opts,
        # colorbar_opts=colorbar_opts,
        colorbar_position="top",
    )

    img2 = hv.Image(ds2).opts(hv.opts.Image(aspect="equal"))
    img2.opts(
        width=WIDTH,
        cmap=COLORS[field],
        color_levels=BOUNDS[field],
        clim=CLIMS[field],
        colorbar=True,
        # cticks=colorbar_opts,
        colorbar_position="top",
        # colorbar_opts=colorbar_opts,
        hooks=[plot_limits],
    )

    # load and plot coastline paths
    paths = list(
        np.load(
            "user-path",
            allow_pickle=True,
        )
    )
    coasts = hv.Path(paths).opts(
        xlim=(0, 1299), ylim=(0, 919), aspect="equal", color="black"
    )

    subtitle = f"Valid Time: {valid} | Lead: {lead} | Level: {level:,} ft"
    pirep_overlay, tamdar_overlay, metars_overlay = self.get_obs()
    plot1 = img1 * coasts * pirep_overlay * metars_overlay * tamdar_overlay
    plot1.opts(
        title=f"IPA-F {field}\n{subtitle}",
        xlabel="",
        ylabel="",
        fontsize=FONTSIZE,
        xticks=0,
        yticks=0,
        legend_position="bottom",
        legend_opts={"click_policy": "hide", "ncols": 5},
    )
    plot2 = img2 * coasts * pirep_overlay * metars_overlay * tamdar_overlay
    plot2.opts(
        title=f"FIP2-AK {field}\n{subtitle}",
        xlabel="",
        ylabel="",
        fontsize=FONTSIZE,
        xticks=0,
        yticks=0,
        legend_position="bottom",
        legend_opts={"click_policy": "hide", "ncols": 5},
    )
    return plot1 + plot2

def create_plot(self):
    """
    Create the map
    """
    return hv.DynamicMap(self.dynamic_plot, kdims=[])

```

Some of the code is commented out, representing our attempts to make the updated colorbar use the ticks and labels we want. But so far, only the first load has the correct labels for the severity field. When we change the “field” parameter, the colorbar will change to the right colors and spacing, but will retain the first set of ticks and labels (ex: 0.5 on probability is labeled “No Icing”, there are no other labels or ticks present).

All help appreciated.

---

<div class="post-metadata">

**Author:** ![ahuang11](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/ahuang11/32/4947_2.png) [@ahuang11](https://discourse.holoviz.org/u/ahuang11)\
**Post date:** [February 18, 2025, 9:33pm UTC](https://discourse.holoviz.org/t/dynamicmap-colorbar-ticks-will-not-update-when-parameter-changes/8591/2 "2025-02-18T21:33:20Z")

</div>

Try dropping `hv.DynamicMap` and only keeping `depends`.

```auto

def create_plot(self):
    """
    Create the map
    """
    return self.dynamic_plot

```

---

<div class="post-metadata">

**Author:** ![lee1](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/lee1/32/7133_2.png) [@lee1](https://discourse.holoviz.org/u/lee1)\
**Post date:** [February 18, 2025, 9:51pm UTC](https://discourse.holoviz.org/t/dynamicmap-colorbar-ticks-will-not-update-when-parameter-changes/8591/3 "2025-02-18T21:51:45Z")

</div>

This does make the ticks behave as desired. The problem now is that when a parameter changes, the maps reset to the default zoom extents. The desired behavior is that the map extents don’t change when parameters update.

---

<div class="post-metadata">

**Author:** ![ahuang11](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/ahuang11/32/4947_2.png) [@ahuang11](https://discourse.holoviz.org/u/ahuang11)\
**Post date:** [February 19, 2025, 1:14am UTC](https://discourse.holoviz.org/t/dynamicmap-colorbar-ticks-will-not-update-when-parameter-changes/8591/4 "2025-02-19T01:14:33Z")

</div>

Might be related to [Plot options not applied when changed interactively · Issue #2982 · holoviz/holoviews · GitHub](https://github.com/holoviz/holoviews/issues/2982)

You may have to manually capture and update the x\_range/y\_range

---

<div class="post-metadata">

**Author:** ![faronium](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/faronium/32/7409_2.png) [@faronium](https://discourse.holoviz.org/u/faronium)\
**Post date:** [January 3, 2026, 2:18am UTC](https://discourse.holoviz.org/t/dynamicmap-colorbar-ticks-will-not-update-when-parameter-changes/8591/5 "2026-01-03T02:18:10Z")

</div>

Has there been a resolution to this? I’m finding this problem maddening. Completely re-rendering the plots at each UI update using param.depends() is very very slow in my case. Everything except the colorbar tick label and location updating works fine. If there’s a github issue associated with this, can someone point me to it? Are there any other workarounds? Pulling my hair out here over something that should be dead simple and dead common.

---

<div class="post-metadata">

**Author:** ![ahuang11](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/ahuang11/32/4947_2.png) [@ahuang11](https://discourse.holoviz.org/u/ahuang11)\
**Post date:** [January 5, 2026, 4:54pm UTC](https://discourse.holoviz.org/t/dynamicmap-colorbar-ticks-will-not-update-when-parameter-changes/8591/6 "2026-01-05T16:54:03Z")

</div>

Does this work for you?

```python
import numpy as np
from bokeh.models import FixedTicker

import holoviews as hv
import panel as pn
import param

hv.extension("bokeh")

class ColorbarController(param.Parameterized):
    mode = param.Integer(default=0)

    def toggle(self, event=None):
        self.mode = (self.mode + 1) % 2

    def view(self, mode): # Accept mode as argument
        # Create some data
        x = np.linspace(0, 10, 50)
        y = np.linspace(0, 10, 50)
        xx, yy = np.meshgrid(x, y)
        z = np.sin(xx) * np.cos(yy)

        # Two different colorbar configurations
        if mode == 0:
            ticks = [(-1, "Low"), (0, "Mid"), (1, "High")]
            clim = (-1, 1)
        else:
            ticks = [(-0.5, "Cold"), (0.5, "Hot")]
            clim = (-0.5, 0.5)

        return hv.Image(
            (x, y, z),
            kdims=["x", "y"],
            vdims=["value"],
        ).opts(
            colorbar=True,
            clim=clim,
            colorbar_opts={
                "major_label_overrides": dict(ticks),
                "ticker": FixedTicker(ticks=[t[0] for t in ticks]),
            },
            width=400,
            height=400,
        )

controller = ColorbarController()

# Pass mode as a stream parameter
dmap = hv.DynamicMap(controller.view, streams=[controller.param.mode])
button = pn.widgets.Button(name="Toggle Colorbar", button_type="primary")
button.on_click(controller.toggle)

pn.Column(
    button,
    dmap,
).show()

```

---

<div class="post-metadata">

**Author:** ![lee1](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/lee1/32/7133_2.png) [@lee1](https://discourse.holoviz.org/u/lee1)\
**Post date:** [January 5, 2026, 5:08pm UTC](https://discourse.holoviz.org/t/dynamicmap-colorbar-ticks-will-not-update-when-parameter-changes/8591/7 "2026-01-05T17:08:44Z")

</div>

I did not resolve this. It was a major headache and I gave up on the functionality I was looking for ☹
