I would like to generate some custom python plots for every row of an input table.
I managed to use the Python View node for that but it is limited for the output to one PNG image at a time.
I was wondering if there is a way to use a classical Python Script node to directly put some PNG plots into a “plot” column, like other types of variable. That would save some execution time.
The simplest way to do this that currently comes to mind would be by using the KNIME Image Processing community contribution which also features an extension for Python. This allows you to wrap numpy.ndarrays in individual KNIPImage objects on Python side which you can put into the output pandas.DataFrame of nodes like the Python Script (1⇒1) node like any other kind of data. They are then translated to ImgPlus data cells on KNIME side which you can convert into PNGs using the ImgPlus to PNG Images node. An example Python script can be found on the page of the Python extension to which I linked above.
Thanks for the answer, I know this method of putting a numpy array into a KNIPImage object, but I was hoping that there could be a possibility to also output directly a PNG, similar to the python view node.
Indeed, the python view node is shipped with a template code that shows how to save the plot as PNG or SVG from matplotlib to a buffer variable. I can possibly get a numpy array from the matplotlib plot but it is less pythonic in a way
For what it’s worth, looking at our Python integration’s source code suggests that KNIME is also capable of directly converting images of Python type PIL.PngImagePlugin.PngImageFile into KNIME image cells. Maybe that’s an alternative (but honestly, I have no idea how to create a PngImageFile and I’ve never seen someone using that functionality so far).
I found a way with SVG not with PNG but that’s fine
That’s actually what is used for the python view node as well, using matplotlib instead of PILimage to save the buffer.
And it turns out that the resulting string of buffer.getvalue() can be stored in a string column, then rendered to an image by pluging a string to SVG node after the python node
The only thing is that the SVG cannot be viewed in the ImageViewer but by increasing the row height and column width the image is scaling accordingly so I’m fine with it.
Trying the same thing with PNG returns the error Execute failed: 'utf8' codec can't decode byte 0x89 in position 0: invalid start byte
By the way, I just realized that the XML string for the SVG figure differs between Python 2/Matplotlib 2.2.3 and Python3/Matplotlib 3.0.3.
In Python3, the string was encoded as byte so the command has to be modified with .decode("utf-8")
did anyone ever have success with PNG columns?
I cannot get it to work, and SVG is too slow for thousands of data points.
With PNG, python produces a byte vector column and if I then use e.g. a “Renderer to Image columns” node, all the images are just white.