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)
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?
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).
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?
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);