# Mapper doesn't update via js callback dynamically

**URL:** <https://discourse.bokeh.org/t/mapper-doesnt-update-via-js-callback-dynamically/10545>\
**Category:** Community Support\
**Created:** [June 10, 2023, 9:13pm UTC](https://discourse.bokeh.org/t/mapper-doesnt-update-via-js-callback-dynamically/10545 "2023-06-10T21:13:34Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sandeep\_Reddy](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/sandeep_reddy/32/6037_2.png) [@Sandeep\_Reddy](https://discourse.bokeh.org/u/Sandeep_Reddy)\
**Post date:** [June 10, 2023, 9:13pm UTC](https://discourse.bokeh.org/t/mapper-doesnt-update-via-js-callback-dynamically/10545/1 "2023-06-10T21:13:34Z")

</div>

The color\_bar doesn’t update for both the radio and multichoice groups. The change doesn’t get transmitted. Everything else (all the other logic) works fine and console.log(mapper) shows the updated min and max values.

```auto

import numpy as np
import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, ColorBar, HoverTool, CustomJS, Div
from bokeh.models.widgets import RadioGroup, MultiChoice
from bokeh.layouts import row
from bokeh.transform import linear_cmap
from bokeh.palettes import Cividis10

def main():
    our_list = ["SAMD11", "HES4"]
    df1 = pd.DataFrame({'SAMD11': [1, 2, 3], 'HES4': [4, 5, 6], 'BIS': [20, 21, 22], 'umap1': [10, 11, 12], 'umap2': [13, 14, 15], 'index': ['A', 'B', 'C']})
    df1["score"] = np.sum(df1[our_list].values, axis=1) # Initially
    OPTIONS = sorted(df1.columns.tolist()[:3])
    source = ColumnDataSource(df1[our_list + ["score", "umap1", "umap2", "index"]])
    df2 = pd.DataFrame({'SAMD11': [-1, -2, -3], 'HES4': [-4, -5, -6], 'BIS': [-20, -21, -22], 'umap1': [-10, -11, -12], 'umap2': [-13, -14, -15], 'index': ['A', 'B', 'C']})
    df2['score'] = None
    mapper = linear_cmap(field_name="score",
                               palette=Cividis10,
                               low=min(source.data["score"]),
                               high=max(source.data["score"]))
    p = figure(
        title="UMAP Visualization",
        x_axis_label="umap1",
        y_axis_label="umap2",
        height=800,
        width=800,
        toolbar_location="above",
        tools=[HoverTool(tooltips=[("Cell Name", "@index")], mode="mouse")])
    p.scatter("umap1",
              "umap2",
              source=source,
              color=mapper,
              line_color=None)
    color_bar = ColorBar(color_mapper=mapper["transform"], width=8)
    p.add_layout(color_bar, "right")

    radio_group = RadioGroup(labels=["File 1", "File 2"], active=0)
    multichoice_group = MultiChoice(value=our_list, options=OPTIONS, width=200, search_option_limit=10)

    radio_callback = CustomJS(
        args=dict(source=source, source1=df1.to_dict(orient='list'), source2=df2.to_dict(orient='list'), multichoice_group=multichoice_group, mapper=mapper),
        code="""
        var our_list = multichoice_group.value;
        var sourceData = this.active === 0 ? source1 : source2;
        var cols = our_list.concat(["score", "umap1", "umap2", "index"]);
        for (var i = 0; i < cols.length; i++) {
            var col = cols[i];
            source.data[col] = sourceData[col];}

        var sumArray = [];
        for (var i = 0; i < source.data['index'].length; i++) {
            var sum = 0;
            for (var j = 0; j < our_list.length; j++) {
                sum += source.data[our_list[j]][i];}
            sumArray.push(sum);
            }    
      
        var updates = { score: [] };
        for (var i = 0; i < sumArray.length; i++) {
            updates.score.push([i, sumArray[i]]);}
        source.patch(updates);
        console.log(source.data);

        mapper.low = parseFloat(Math.min.apply(null, sumArray));
        mapper.high = parseFloat(Math.max.apply(null, sumArray));
        console.log(mapper);
        """)
    multichoice_callback = CustomJS(args=dict(source=source, source1=df1.to_dict(orient='list'), source2=df2.to_dict(orient='list'), radio_group=radio_group, mapper=mapper),
        code="""
        var our_list = this.value;
        var sourceData = radio_group.active === 0 ? source1 : source2;
        var cols = our_list.concat(["score", "umap1", "umap2", "index"]);

        for (var i = 0; i < cols.length; i++) {
            var col = cols[i];
            if (!(col in source.data)) {
                source.data[col] = sourceData[col];}
            }
        for (var col in source.data) {
            if (col != 'level_0' && !cols.includes(col)) {
                delete source.data[col];}
            }  

        var sumArray = [];
        for (var i = 0; i < source.data['index'].length; i++) {
            var sum = 0;
            for (var j = 0; j < our_list.length; j++) {
                sum += source.data[our_list[j]][i];}
            sumArray.push(sum);
            }         

        var updates = { score: [] };
        for (var i = 0; i < sumArray.length; i++) {
            updates.score.push([i, sumArray[i]]);}
        source.patch(updates);
        console.log(source.data);       

        mapper.low = parseFloat(Math.min.apply(null, sumArray));
        mapper.high = parseFloat(Math.max.apply(null, sumArray));
        console.log(mapper);
        """)

    radio_group.js_on_change("active", radio_callback)
    multichoice_group.js_on_change("value", multichoice_callback)
    layout = row([multichoice_group, radio_group, p])
    show(layout)

if __name__ == " __main__":
    main()

```

---

<div class="post-metadata">

**Author:** ![system](https://discourse-uploads.bokeh.org/original/2X/1/14eb24f9e10e4e9b78e3f10f66c04ffa96446e5a.svg) [@system](https://discourse.bokeh.org/u/system)\
**Post date:** [September 8, 2023, 9:13pm UTC](https://discourse.bokeh.org/t/mapper-doesnt-update-via-js-callback-dynamically/10545/2 "2023-09-08T21:13:45Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
