Updating legend labels using a callback?

Hi there,

I have two questions about an interactive plot I’m making. It’s hosted here.

  1. Is it possible to update legend labels once my plot is hosted on a bokeh server?

I seem to be able to edit the label values before hosting using the following function:

def update_legend():
    for legend in p.legend:
        for legend_item, new_value in zip(legend.items,
                                          [df.loc[f.name].stats.short if f.name is not None else None for f in flist]):
            legend_item.label['value'] = new_value

However, once the plot is hosted on a bokeh server (using heroku) I get the following error, when the function is used in a callback:

2022-12-02T09:58:27.597095+00:00 app[web.1]:     legend_item.label['value'] = new_value
2022-12-02T09:58:27.597095+00:00 app[web.1]: TypeError: 'NoneType' object does not support item assignment

I have a set of ColumnDataSources linked to a set of Patch plots. Each time I load and remove data I want to update the corresponding legend using the callback posted above.

  1. Is there a way to make a figure have equal axis scales? Especially when the legend is positioned outside of the plot? Currently my figure is distorted (see below).

The code for the radar plot is:

# radar plot
p = figure(title="", toolbar_location=None, height=700, width=700)
p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None
p.axis.minor_tick_line_color = None
p.xaxis.major_tick_line_color = None  # turn off x-axis major ticks
p.xaxis.minor_tick_line_color = None  # turn off x-axis minor ticks
p.yaxis.major_tick_line_color = None  # turn off y-axis major ticks
p.yaxis.minor_tick_line_color = None  # turn off y-axis minor ticks
p.xaxis.major_label_text_font_size = '0pt'  # turn off x-axis tick labels
p.yaxis.major_label_text_font_size = '0pt'  # turn off y-axis tick labels
p.x_range.start = -0.6
p.x_range.end = 1.6
p.y_range.start = -0.1
p.y_range.end = 1.1
p.match_aspect = True
p.outline_line_color = None
p.axis.visible = False
p.line(x="x", y="y", source=radar_annotation_data, color='black')
labels = LabelSet(x="x", y="y", text="text", source=radar_annotation_data, text_font_size="10pt",
                  text_align='text_align', text_baseline='text_baseline')
p.add_layout(labels)
lis = []
for i in range(len(flist)):
    renderer = p.patch(x='x', y='y', source=flist[i], fill_alpha=0, fill_color=distribution_colours[i],
                       line_color=distribution_colours[i])
    li = LegendItem(label="", renderers=[renderer])
    lis.append(li)
f_legend = Legend(items=lis, location='center', orientation="vertical", glyph_height=15, glyph_width=15,
                  label_text_font_size="10pt")
# p.add_layout(f_legend)
p.add_layout(f_legend, 'right')

Yes, you can pass match_aspect=True to figure, but note that aspect matching only functions with automatic data-ranges. If you explicitly set range start/end values yourself Bokeh will not override your values, even to match aspect.

For the error, it’s not possible to say much without a Minimal Reproducible Example to see exactly what is going on and to be able to run and investigate. My suggestion is to pare down everything to a (complete) toy example that just demonstrates how you are trying to update the legend so that we can focus on that.

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