Python script node does not visualize the Bokeh library output

I am trying to integrate this Python script in KNIME:

It is an interactive python visualization of clusters using Bokeh library. In a regular environment, I execute it with a command line:
“bokeh serve -show clustering”.

If I try to embed a Python Script with the code, I only get status “the python3Command is controlled by a variable”.

However, if I am trying a much simpler code in Python Script node, like this, the visualization opens with no issues in an external browser:

from bokeh.plotting import figure, output_file, show

# Basic plotting
# prepare some data
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]

# output to static HTML file
output_file("lines.html")

# create a new plot with a title and axis labels
p = figure(title="simple line example", x_axis_label='x', y_axis_label='y')

# add a line renderer with legend and line thickness
p.line(x, y, legend_label="Temp.", line_width=2)

# show the results
show(p)

…outputs:

What is the best way to integrate a complex Python/Bokeh application into the KNIME flow?

Hallo @fbagirov,

could you maybe share your example, so I can have a look at it. The sentence “The python3Command is controlled by a variable” is just simply telling you that you are passing a flow variable to the python3Command to overwriting your inputs. Can you check the Flow Variables Tab and maybe remove this? Or did you set this Flow Variable on purpose?
Did you try to execute your script? Did you get any errors?

Best,
Janina

Hi @fbagirov

I solved it by storing the bokeh app script/folder in the workflow data area, calling
subprocess.run([sys.executable,"-m","bokeh", "serve", "--port", "5100", flow_variables['App path']
in a Python node and afterwards make a Generic Javascript View embed the served HTML from the server running in the background with sth like this:

var body = document.getElementsByTagName('body')[0];
var address = "http://localhost:5100"; 
var html = "<iframe src=\""+ address +"\" height=\"1000px\" width=\"100%\"></iframe>";
body.innerHTML = html;

P.S.: Make sure to include a way to stop your Bokeh server (i.e. onExit or with an extra button).

Best
Julianus

1 Like

The Bokeh documentation explains a way of creating a JSON configuration in Python and do the plotting in Javascript.
This sounds like a good way of integrating Python-configured Bokeh-plots in a Generic Javascript View in KNIME. But I couldn’t get it working.

In Python I created a flow variable containing the JSON-content like:

import pandas as pd
import json
from bokeh.plotting import figure
from bokeh.embed import json_item

p = figure()
p.circle(1, 2)
flow_variables['json'] = json.dumps(json_item(p, "myplot"))

But the to lines of code in Javascript from the Bokeh documentation are not enough to get the view working. Could somebody provide an example, to get that working?

Lately I got it working:
Python:

from json import dumps

from bokeh.plotting import figure
from bokeh.embed import json_item

#-----------------------------------------------
# do something with bokeh
plot = figure(width = 800, height = 450)
plot.circle([1,2], [3,4])
#-----------------------------------------------


# export the plot to json to Knime variable
item_text = dumps(json_item(plot))
flow_variables['json'] = item_text

# get the bokeh version as Knime variable
import bokeh
flow_variables['bokeh_version']=bokeh.__version__

and the Generic JavaScript View connected via a variable Port

//based on https://forum.knime.com/t/generic-javascript-view-with-bokeh/15210/2
// Function to load css file of Bokeh
function loadCss(url) {
    var link = document.createElement("link");
    link.type = "text/css";
    link.rel = "stylesheet";
    link.href = url;
    document.getElementsByTagName("head")[0].appendChild(link);
}

// Needed to load the bokeh scripts with require.js
requirejs.config({
	paths: {
		bokeh: "https://cdn.pydata.org/bokeh/release/bokeh-$${Sbokeh_version}$$.min",
		bokehApi: "https://cdn.pydata.org/bokeh/release/bokeh-api-$${Sbokeh_version}$$.min"
	},
	shim: {
		bokeh: {
			exports: "Bokeh"
		},
		bokehApi: {
			deps: ["bokeh"]
		}
	}
});

// Inside this function Bokeh is available
require(["bokeh", "bokehApi"], function (Bokeh) {

// Function to load css file of Bokeh
loadCss("https://cdn.pydata.org/bokeh/release/bokeh-$${Sbokeh_version}$$.min.css");

//-----------Begin of Bokeh ------------------
var item_text= '$${Sjson}$$';
item = JSON.parse(item_text);
Bokeh.embed.embed_item(item, "my_bokeh_plot");
//-----------End of Bokeh------------------
});

//Create the Bokeh HTML element 
var div = document.createElement('DIV');
div.setAttribute('id', 'my_bokeh_plot');
document.body.append(div);
2 Likes

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