I’m trying to create a function in JavaScript that will update the theme of my Bokeh plot.
I use this to set the theme of my plot at the start of the function that creates the plot
Bokeh.require("core/properties").use_theme(Bokeh.Themes.dark_minimal); //Set theme for graph
The purpose of what I want is because users will print the graph and different themes will be useful for accessibility.
It seems if I use the same line of code as above, it will only set the theme for elements yet to be created.
Eg.
Set theme to dark minimal
make plot
set theme to light minimal
make the legend for the plot
The result of the above is a plot with dark minimal theme and a legend with a light minimal theme (although legend looks a bit broken)
What I want is to be able to create the plot with dark minimal theme and then later after the plot is generated, be able to change the theme to whatever I want.
I’m using BokehJS 3.0.3
I can add a code example if neccessary but don’t think it should be needed.
More or less, themes only install a different set of default values before first-use, so short answer is not at present. There is a tangentially related discussion here (focused on light/dark mode)
cc @mateusz please correct if I have anything out of date regarding the current status. AFAIK we would need to add a mechanism to force a “global re-evaluate” in order that switching themes can have an effect.
// Define a dictionary of theme names and their associated theme functions
const themes = {
'dark': applyDarkTheme
};
// Define the dark theme function that takes a Bokeh figure object as an argument
function applyDarkTheme(fig) {
// Set the individual attributes on the figure to give it a dark theme
fig.background_fill_color = "#282828";
fig.border_fill_color = "#282828";
fig.xaxis.axis_line_color = "white";
fig.yaxis.axis_line_color = "white";
fig.xaxis.major_tick_line_color = "white";
fig.yaxis.major_tick_line_color = "white";
fig.xaxis.minor_tick_line_color = "white";
fig.yaxis.minor_tick_line_color = "white";
fig.xaxis.major_label_text_color = "white";
fig.yaxis.major_label_text_color = "white";
fig.xaxis.minor_label_text_color = "white";
fig.yaxis.minor_label_text_color = "white";
fig.xgrid.grid_line_color = "#8c8c8c";
fig.ygrid.grid_line_color = "#8c8c8c";
fig.xgrid.grid_line_alpha = 0.3;
fig.ygrid.grid_line_alpha = 0.3;
fig.title.text_color = "white";
}
// Define the function that applies the specified theme to all the root objects in all the Bokeh documents
function changeTheme(themeName) {
// Get the theme function associated with the specified theme name
const themeFunc = themes[themeName];
// If the theme function exists, apply it to all the root objects in all the Bokeh documents
if (themeFunc) {
for (let doc of Bokeh.documents) {
for (let root of doc.roots()) {
themeFunc(root);
}
}
} else {
// If the theme function does not exist, log an error message to the console
console.error(`Theme "${themeName}" not found`);
}
}
AMAZING! That’s exactly what I wanted @Alex_Verdaguer Thank you very much.
Although there is one more problem: The legend doesnt get updated with the new theme, was confused for a sec writing this comment, but solved it really easily actually, just added these lines to the theme function:
Sure if this work that is great but it should be clear this is a bandaid, at best, since it does not recursively traverse the object graph and assumes one figure at the root.