How to export SVG with Python view node in Knime 4.1.2 (windows 10 64)

Hi everyone,
I really hope you’re all doing fine.

I juste tried to create an automatic multi y axis plot with python view, and I’m now trying to export the result as svg, but it always ends with “Image (inactive port object)” while it perfectly works when I try to export the result as a PNG.

Here is the code, would you accept to give some help ?

from io import BytesIO
from io import StringIO
from plotly.offline import plot
import plotly.graph_objects as go
import pandas as pd

df = input_table

columns = list(df.columns)

first = columns.pop(0)

fig = go.Figure()

df[first] = pd.to_datetime(df[first], infer_datetime_format=True)
df[first] = df[first].apply(lambda x: x.strftime('%Y-%d-%mT%H:%M'))

columns = columns[:6]

i = 1
colors = ["red", "blue", "green", "cyan", "indigo", "gray", "purple", "yellow", "orange"]

for col in columns :
    
    fig.add_trace(go.Scatter(
            x = df[first],
            y = df[col],
            name = "{0} data".format(col),
            yaxis = "y{0}".format(i),
            line_color = colors[i - 1],
            type='scatter',
            mode = 'markers+lines'
            ))
    i += 1

domain = [0.15, 0.85]

init_layout = dict(
        xaxis=dict(domain=domain,
                   type='date')
        )

i = 1


step_right = 0.0
step_left = 0.0

for col in columns:
    
    if (i == 1) :
        init_layout.update({
                "yaxis{0}".format(i) : dict(
                        title = "yaxis{0} title".format(i),
                        titlefont = dict(color = colors[i - 1]),
                        tickfont = dict(color = colors[i - 1])
                        )
                })
        step_left += 0.05
    else :
        if (i % 2 == 0):
            init_layout.update({
                    "yaxis{0}".format(i) : dict(
                        title = "yaxis{0} title".format(i),
                        titlefont = dict(color = colors[i - 1]),
                        tickfont = dict(color = colors[i - 1]),
                        anchor = "free",
                        overlaying = "y",
                        side = "right",
                        position = max(domain) + step_right
                        )
                    })
            step_right += 0.05
        else :
            init_layout.update({
                    "yaxis{0}".format(i) : dict(
                        title = "yaxis{0} title".format(i),
                        titlefont = dict(color = colors[i - 1]),
                        tickfont = dict(color = colors[i - 1]),
                        anchor = "free",
                        overlaying = "y",
                        side = "left",
                        position = min(domain) - step_left
                        )
                    })
            step_left += 0.05
    i += 1
    
fig.update_layout(init_layout)
fig.update_layout(
        title_text = "test multi axes",
        width=1500,
        height=755,
        autosize=True,
        margin=dict(
            l=2,
            r=2,
            b=50,
            t=50,
            pad=2
            ),
        legend=dict(
            orientation='h'
            ),
        )

fig.update_yaxes(automargin=True)

fig_bytes = fig.to_image(format='svg')
buffer = BytesIO(fig_bytes)
text_obj = buffer.read().decode("utf-8")

buffer = StringIO(text_obj)

# Create plot and write it into the buffer

# The output is the content of the buffer
output_image = '<svg' + buffer.getvalue().split('<svg')[1]

Thank you very much !

1 Like

Hi @vincent_m,

I believe you need to include the XML header (or, in general, supply a well-formed XML-formatted string). So something like <?xml version="1.0"encoding="utf-8"?> should be prepended to the string.

Marcel

2 Likes

Hi Marcel,

Thank you very much for your quick answer. I’m going to try it right now.

Vincent

Hello there,

I come back to you with bad news. Unfortunately, I’m still not able to generate the SVG outport with the python view node using plotly.
If I’m correct, my outport should be a string decoding my svg bytes right ?

So here is the output of my svg string :

b'<svg class="main-svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="600" style="" viewBox="0 0 1000 600"><rect x="0" y="0" width="1000" height="600" style="fill: rgb(255, 255, 255); fill-opacity: 1;"/><defs id="defs-5ac9bd"><g class="clips"><clipPath id="clip5ac9bdxyplot" class="plotclip"><rect width="697.1999999999999" height="455"/></clipPath><clipPath id="clip5ac9bdxy2plot" class="plotclip"><rect width="697.1999999999999" height="455"/></clipPath><clipPath id="clip5ac9bdxy3plot" class="plotclip"><rect width="697.1999999999999" height="455"/></clipPath><clipPath id="clip5ac9bdxy4plot" class="plotclip"><rect width="697.1999999999999" height="455"/></clipPath><clipPath id="clip5ac9bdxy5plot" class="plotclip"><rect width="697.1999999999999" height="455"/></clipPath><clipPath id="clip5ac9bdxy6plot" class="plotclip"><rect width="697.1999999999999" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdx"><rect x="151.4" y="0" width="697.1999999999999" height="600"/></clipPath><clipPath class="axesclip" id="clip5ac9bdy"><rect x="0" y="50" width="1000" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdxy"><rect x="151.4" y="50" width="697.1999999999999" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdy2"><rect x="0" y="50" width="1000" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdxy2"><rect x="151.4" y="50" width="697.1999999999999" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdy3"><rect x="0" y="50" width="1000" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdxy3"><rect x="151.4" y="50" width="697.1999999999999" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdy4"><rect x="0" y="50" width="1000" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdxy4"><rect x="151.4" y="50" width="697.1999999999999" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdy5"><rect x="0" y="50" width="1000" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdxy5"><rect x="151.4" y="50" width="697.1999999999999" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdy6"><rect x="0" y="50" width="1000" height="455"/></clipPath><clipPath class="axesclip" id="clip5ac9bdxy6"><rect x="151.4" y="50" width="697.1999999999999" height="455"/></clipPath></g><g class="gradients"/></defs><g class="bglayer"><rect class="bg" x="149.4" y="48" width="701.1999999999999" height="459" style="fill: rgb(229, 236, 246); fill-opacity: 1; stroke-width: 0;"/></g><g class="layer-below"><g class="imagelayer"/><g class="shapelayer"/></g><g class="cartesianlayer"><g class="subplot xy"><g class="layer-subplot"><g class="shapelayer"/><g class="imagelayer"/></g><g class="gridlayer"><g class="x"><path class="xgrid crisp" transform="translate(188.77,0)" d="M0,50v455" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="xgrid crisp" transform="translate(263.24,0)" d="M0,50v455" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="xgrid crisp" transform="translate(337.71000000000004,0)" d="M0,50v455" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="xgrid crisp" transform="translate(412.19000000000005,0)" d="M0,50v455" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="xgrid crisp" transform="translate(486.65999999999997,0)" d="M0,50v455" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="xgrid crisp" transform="translate(561.13,0)" d="M0,50v455" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="xgrid crisp" transform="translate(635.6,0)" d="M0,50v455" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="xgrid crisp" transform="translate(710.0699999999999,0)" d="M0,50v455" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="xgrid crisp" transform="translate(784.55,0)" d="M0,50v455" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/></g><g class="y"><path class="ygrid crisp" transform="translate(0,452.58)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="ygrid crisp" transform="translate(0,361.74)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="ygrid crisp" transform="translate(0,270.9)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="ygrid crisp" transform="translate(0,180.06)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="ygrid crisp" transform="translate(0,89.22)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/></g><g class="y2"><path class="y2grid crisp" transform="translate(0,452.29)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y2grid crisp" transform="translate(0,374.51)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y2grid crisp" transform="translate(0,296.74)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y2grid crisp" transform="translate(0,218.96)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y2grid crisp" transform="translate(0,141.18)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y2grid crisp" transform="translate(0,63.41)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/></g><g class="y3"><path class="y3grid crisp" transform="translate(0,497.4)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y3grid crisp" transform="translate(0,451.09)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y3grid crisp" transform="translate(0,404.78)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y3grid crisp" transform="translate(0,358.47)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y3grid crisp" transform="translate(0,312.16)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y3grid crisp" transform="translate(0,265.85)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y3grid crisp" transform="translate(0,219.54)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y3grid crisp" transform="translate(0,173.23000000000002)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y3grid crisp" transform="translate(0,126.92)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y3grid crisp" transform="translate(0,80.61)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/></g><g class="y4"><path class="y4grid crisp" transform="translate(0,453.63)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y4grid crisp" transform="translate(0,374.27)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y4grid crisp" transform="translate(0,294.90999999999997)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y4grid crisp" transform="translate(0,215.55)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y4grid crisp" transform="translate(0,136.19)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y4grid crisp" transform="translate(0,56.83)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/></g><g class="y5"><path class="y5grid crisp" transform="translate(0,467)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y5grid crisp" transform="translate(0,400.04)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y5grid crisp" transform="translate(0,333.08)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y5grid crisp" transform="translate(0,266.12)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y5grid crisp" transform="translate(0,199.15)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y5grid crisp" transform="translate(0,132.19)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y5grid crisp" transform="translate(0,65.23)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/></g><g class="y6"><path class="y6grid crisp" transform="translate(0,421.79)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y6grid crisp" transform="translate(0,338.38)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y6grid crisp" transform="translate(0,254.98)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y6grid crisp" transform="translate(0,171.57999999999998)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/><path class="y6grid crisp" transform="translate(0,88.18)" d="M151.4,0h697.1999999999999" style="stroke: rgb(255, 255, 255); stroke-opacity: 1; stroke-width: 1px;"/></g></g><g class="zerolinelayer"/><path class="xlines-below"/><path class="ylines-below"/><g class="overlines-below"><path class="xy2-x"/><path class="xy2-y"/><path class="xy3-x"/><path class="xy3-y"/><path class="xy4-x"/><path class="xy4-y"/><path class="xy5-x"/><path class="xy5-y"/><path class="xy6-x"/><path class="xy6-y"/></g><g class="xaxislayer-below"/><g class="yaxislayer-below"/><g class="overaxes-below"><g class="xy2-x"/><g class="xy2-y"/><g class="xy3-x"/><g class="xy3-y"/><g class="xy4-x"/><g class="xy4-y"/><g class="xy5-x"/><g class="xy5-y"/><g class="xy6-x"/><g class="xy6-y"/></g><g class="plot" transform="translate(151.4, 50)" clip-path="url(\'#clip5ac9bdxyplot\')"><g class="scatterlayer mlayer"><g class="trace scatter trace290850" style="stroke-miterlimit: 2; opacity: 1;"><g class="fills"/><g class="errorbars"/><g class="lines"><path class="js-line" d="M38.61,26.95L42.33,26.5L42.95,43.72L44.2,153.22L44.82,153.22L45.44,153.28L46.06,229.84L46.68,323.3L47.3,314.28L47.92,283.84L48.54,272.75L49.16,247.4L51.64,265.69L52.26,257.07L52.88,167.4L53.5,169.72L54.13,110.72L54.75,152.69L55.37,73.13L55.99,34.51L56.61,42.4L57.23,42.85L59.09,42.86L59.71,82.36L61.57,264.55L62.19,261.47L62.81,266.6L63.43,265.3L64.05,242L64.68,180.91L66.54,53.42L67.16,118.32L68.4,137.33L69.02,137.94L70.26,207.6L70.88,169.09L72.12,28.07L72.74,27.86L75.23,26.92L75.85,57.54L77.09,155.27L77.71,198.23L78.33,162.67L78.95,74.74L79.57,76.65L80.19,87.56L80.81,96.39L81.43,127.61L82.67,38.37L83.29,125.6L83.91,168.35L84.53,152L85.78,28.15L86.4,27.55L88.88,26.95L89.5,79.02L90.74,242.85L91.36,220.78L91.98,214.92L92.6,183.28L93.22,186.46L93.84,211.69L94.46,224.67L95.08,186.8L96.95,28.02L97.57,27.42L105.01,26.68L105.63,107.13L107.5,163.47L108.12,119.58L108.74,52.75L109.36,140.41L109.98,119.64L110.6,29.21L112.46,63.37L113.08,111.94L113.7,200.47L114.32,119.26L115.56,28.7L116.19,28.32L119.91,27.81L120.53,87.71L121.15,157.27L121.77,105.78L122.39,157.08L123.01,107.13L123.63,57.08L124.25,90.75L125.49,100.1L126.11,100.54L127.98,101.18L128.6,101.44L133.56,101.92L134.18,102.35L134.8,102.35L135.42,113.94L136.04,162.45L136.66,74.65L137.29,36.41L137.91,176.13L139.15,284.56L139.77,246.58L141.01,135.24L141.63,152.58L142.25,65.72L142.87,182.11L144.11,248.73L144.73,193.16L145.97,28.37L146.59,27.69L147.84,27.41L148.46,50.74L150.32,276.66L150.94,253.37L151.56,215.26L152.18,225.9L152.8,228.48L153.42,244.17L155.28,27.97L155.9,27.41L162.11,26.95L162.73,27.01L163.97,26.78L164.59,65.34L165.83,137.78L166.45,137.78L168.32,137.78L168.94,151.37L169.56,155.95L170.18,205.91L172.04,34.96L172.66,62.23L173.28,163.46L173.9,130.16L174.52,177.36L175.14,127.93L176.38,27.77L177,27.41L181.35,27.22L181.97,30.63L183.21,102.35L183.83,102.35L184.45,115.4L185.07,168.8L186.31,174.44L186.93,186.71L188.17,28.7L188.8,27.95L196.24,27.41L196.86,27.41L198.1,27.41L198.72,46.7L199.97,212.84L200.59,182.95L201.21,223.31L201.83,117.19L203.07,26.95L203.69,26.55L205.55,136.55L206.17,137.98L207.41,38.03L208.03,67.42L209.28,143.59L209.9,51.49L211.14,188.4L211.76,216.88L212.38,234.6L213,126.33L214.24,28.11L214.86,27.54L217.34,27.41L217.96,81.13L218.58,207.5L219.2,84.5L219.83,97.86L220.45,159.19L221.07,160.81L221.69,226.86L222.31,222.97L222.93,171.47L224.79,27.96L225.41,27.79L227.27,27.41L227.89,27.41L232.24,26.95L232.86,35.7L234.1,156.4L234.72,169.99L235.96,60.72L236.58,141.74L237.2,83.69L237.82,90.12L238.44,132.81L239.68,155.47L240.31,161.41L240.93,219.47L241.55,112.03L242.79,27.61L243.41,27.41L245.27,27.37L245.89,59.21L247.13,274.43L247.75,259.35L248.99,215.72L249.61,240.55L250.23,228.44L250.86,172.59L252.1,27.86L252.72,27.41L255.82,26.95L256.44,26.95L258.3,26.95L258.92,52.5L260.16,83.18L260.79,83.73L263.27,83.93L263.89,148.7L264.51,124.32L265.13,45.46L265.75,28.18L266.37,79.76L267.61,333.96L268.23,333.16L270.09,113.53L270.71,130.1L271.34,126.49L271.96,197.9L273.2,284.03L273.82,284.42L275.06,249.03L275.68,200.07L276.92,28.92L277.54,28.17L280.64,27.41L281.26,27.41L281.89,46.98L282.51,141.78L283.13,274.82L283.75,248.25L284.37,264.37L285.61,174.03L286.23,189.24L288.09,27.45L288.71,27.11L291.82,26.95L292.44,26.95L294.3,26.95L294.92,29.94L296.16,245.59L296.78,128.04L297.4,37.87L298.02,47.5L298.64,141.57L299.26,155.8L299.88,151.2L300.5,227.21L301.12,157.13L301.74,124.12L302.37,177.39L302.99,181.53L303.61,215.76L304.23,219.79L304.85,164.6L305.47,179.51L306.09,132.77L306.71,131.5L307.33,51.53L308.57,27.41L309.19,37.33L310.43,43.36L311.05,43.76L312.29,44.05L312.92,164.63L314.16,262.25L314.78,245.36L315.4,257.27L316.02,164.77L316.64,161.13L317.26,205.64L319.12,27.63L319.74,27.34L321.6,26.95L322.22,26.95L325.33,26.95L325.95,51.09L327.19,220.89L327.81,80.12L328.43,132.13L329.05,270.07L330.29,299.02L330.91,299.52L331.53,287.39L332.15,157.45L332.77,134.07L333.4,246.83L334.02,247.44L334.64,263.94L335.88,278.76L336.5,282.12L338.36,314.39L338.98,315.87L339.6,318.1L340.22,324.63L341.46,321.01L342.08,320.87L343.32,336.55L343.95,338.54L345.19,338.54L345.81,345.13L347.05,360.57L347.67,362.16L348.29,381.26L348.91,376.7L349.53,374.28L350.15,378.08L351.39,374.18L352.01,379.42L353.25,379.42L353.88,389.93L355.74,400.29L356.36,390.34L356.98,397.08L357.6,396.91L358.22,401.34L358.84,400.23L359.46,397.39L360.08,398.83L360.7,405.28L361.32,404.95L361.94,399.86L362.56,394.94L363.18,406.81L364.43,396.68L365.05,396.68L365.67,407.08L366.29,401.4L366.91,405.08L367.53,399.76L368.15,399.48L368.77,408.08L369.39,407.7L370.01,401.55L370.63,410.98L371.25,410.86L371.87,409.86L373.11,405.29L373.73,410.48L374.35,410.8L374.98,406.21L375.6,418.44L376.22,418.33L376.84,408.94L377.46,408.94L378.08,413.94L378.7,409.92L379.32,414.42L380.56,410.76L381.18,410.76L381.8,410.76L382.42,415.92L383.04,422.64L383.66,420.02L384.91,413.47L385.53,413.48L386.15,413.48L386.77,412.17L388.01,413.48L388.63,413.48L389.25,418.61L389.87,415.36L394.21,415.49L394.83,423.44L395.46,420.88L396.08,424.75L396.7,425.29L397.32,419.24L399.18,418.93L399.8,418.93L406.63,418.93L407.25,428.5L407.87,427.74L408.49,428.27L410.35,428.27L410.97,422.57L412.21,421.93L412.83,423.47L413.45,421.26L414.07,179.93L414.69,29.22L415.31,221.91L416.56,402.64L417.18,400.38L418.42,395.63L419.04,370.72L420.28,384.64L420.9,377.39L422.76,259.87L423.38,180.32L424,149.92L424.62,251.52L427.11,29.23L427.73,29.16L430.21,28.32L430.83,28.28L431.45,29.83L432.07,65.36L433.31,100.99L433.93,117.11L434.55,120.58L435.17,135.88L435.79,136.11L436.41,168.78L437.66,172.3L438.28,172.3L445.1,172.3L445.72,181.28L446.34,158.74L446.97,45.18L447.59,27.26L448.21,65.58L449.45,143.72L450.07,135.71L450.69,121.14L451.31,30.03L451.93,32.68L452.55,80.82L454.41,82.82L455.03,82.82L461.24,82.82L461.86,93.18L463.1,119.61L463.72,131.84L464.96,155.26L465.58,165.08L466.2,205.36L466.82,115.26L468.07,27.86L468.69,27.86L476.75,27.41L477.37,99.3L478.62,139.14L479.24,156.7L479.86,34.09L480.48,95.05L481.72,138.23L482.34,155.78L483.58,178.36L484.2,148.69L485.44,27.99L486.06,30.21L486.68,46.7L487.3,116.14L488.55,119.15L489.17,119.16L492.27,119.16L492.89,142.32L493.51,126.27L494.13,30.42L494.75,40.6L495.37,112.39L496.61,120.07L497.23,120.07L507.16,120.66L507.78,120.97L508.4,120.97L509.03,151.37L509.65,143.08L510.27,78.04L511.51,121.38L512.13,143.96L513.37,161.19L513.99,53.34L515.23,27.84L515.85,27.51L516.47,29.34L517.09,42.78L522.68,44.22L523.3,85.12L524.54,216.48L525.16,208.27L525.78,142.44L526.4,51.4L527.02,96.29L528.26,180.34L528.88,89.18L530.13,28.32L530.75,28.32L539.43,27.28L540.06,44.64L542.54,293L543.16,249.45L543.78,205.47L544.4,242.41L545.02,191.22L545.64,215.79L546.26,258.48L546.88,219.32L548.12,106.31L548.74,101.2L549.98,27.99L550.61,27.86L553.09,27.41L553.71,46.4L555.57,137.26L556.19,137.33L569.84,137.78L570.46,146.84L571.09,180.38L571.71,124.62L572.33,190.17L572.95,183.07L573.57,81.97L574.19,63.27L574.81,134.23L575.43,150.07L576.05,46.77L576.67,27.8L577.29,69.96L578.53,240.32L579.15,213.39L580.39,28.26L581.01,27.86L583.5,27.41L584.12,115.93L584.74,186.78L585.36,121.13L585.98,131.26L586.6,99.26L587.22,30.37L587.84,45.33L588.46,75.64L589.08,215.77L589.7,180.44L590.32,43.54L591.57,27.86L592.19,27.49L599.63,26.95L600.25,67.76L601.49,156.15L602.12,161.44L602.74,159.45L603.36,173.53L603.98,92.59L604.6,105.43L605.22,173.59L606.46,218.42L607.08,105.18L607.7,47.88L608.32,189.04L608.94,247.27L609.56,126.19L610.8,27.41L611.42,27.41L613.91,27.4L614.53,104.47L615.15,227.67L615.77,205.43L616.39,211.88L617.01,242.88L617.63,189.75L618.87,249.36L619.49,188.89L620.73,28.85L621.35,28.35L629.42,27.41L630.04,64.9L631.28,120.97L631.9,130.35L633.15,323.69L633.77,182.12L635.01,27.43L635.63,29.08L636.87,118.85L637.49,119.45L640.59,119.61L641.21,119.61L644.32,119.61L644.94,120.38L646.18,195.05L646.8,104.95L647.42,59.44L648.04,100.49L649.9,101.9L650.52,101.9L658.59,101.94" style="vector-effect: non-scaling-stroke; fill: none; stroke: rgb(255, 0, 0); stroke-opacity: 1; stroke-width: 2px; opacity: 1;"/></g><g class="points"><path class="point" transform="translate(38.61,26.95)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 0, 0); fill-opacity: 1;"/><path class="point" transform="translate(39.23,26.95)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 0, 0); fill-opacity: 1;"/><path class="point" transform="translate(39.85,26.95)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 0, 0); fill-opacity: 1;"/><path class="point" transform="translate(40.47,26.95)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 0, 0); fill-opacity: 1;"/><path class="point" transform="translate(41.09,26.95)" [etc.]
Reached maximum output limit, omitted 1050375 characters

Sorry for the ugly format, but has anyone got a solution for this ? I still can’t have any image outport with the node

1 Like

Here is an edit of my code, I added the xml header, but it still doesn’t work. Note that the png export works really well, but when it comes to SVG, I can’t have the node’s output.

from io import BytesIO
from plotly.offline import plot
import plotly.graph_objects as go
import pandas as pd

df = input_table

columns = list(df.columns)

first = columns.pop(0)

fig = go.Figure()

df[first] = pd.to_datetime(df[first], infer_datetime_format=True)
df[first] = df[first].apply(lambda x: x.strftime('%Y-%d-%mT%H:%M'))

columns = columns[:6]

i = 1
colors = ["red", "blue", "green", "cyan", "indigo", "gray", "purple", "yellow", "orange"]

for col in columns :
    
    fig.add_trace(go.Scatter(
            x = df[first],
            y = df[col],
            name = "{0} data".format(col),
            yaxis = "y{0}".format(i),
            line_color = colors[i - 1],
            type='scatter',
            mode = 'markers+lines'
            ))
    i += 1

domain = [0.15, 0.85]

init_layout = dict(
        xaxis=dict(domain=domain,
                   type='date')
        )

i = 1


step_right = 0.0
step_left = 0.0

for col in columns:
    
    if (i == 1) :
        init_layout.update({
                "yaxis{0}".format(i) : dict(
                        title = "yaxis{0} title".format(i),
                        titlefont = dict(color = colors[i - 1]),
                        tickfont = dict(color = colors[i - 1])
                        )
                })
        step_left += 0.05
    else :
        if (i % 2 == 0):
            init_layout.update({
                    "yaxis{0}".format(i) : dict(
                        title = "yaxis{0} title".format(i),
                        titlefont = dict(color = colors[i - 1]),
                        tickfont = dict(color = colors[i - 1]),
                        anchor = "free",
                        overlaying = "y",
                        side = "right",
                        position = max(domain) + step_right
                        )
                    })
            step_right += 0.05
        else :
            init_layout.update({
                    "yaxis{0}".format(i) : dict(
                        title = "yaxis{0} title".format(i),
                        titlefont = dict(color = colors[i - 1]),
                        tickfont = dict(color = colors[i - 1]),
                        anchor = "free",
                        overlaying = "y",
                        side = "left",
                        position = min(domain) - step_left
                        )
                    })
            step_left += 0.05
    i += 1
    
fig.update_layout(init_layout)
fig.update_layout(
        title_text = "test multi axes",
        width=flow_variables['Largeur'],
        height=flow_variables['Hauteur'],
        autosize=True,
        margin=dict(
            l=2,
            r=2,
            b=50,
            t=50,
            pad=2
            ),
        legend=dict(
            orientation='h'
            ),
        )

fig.update_yaxes(automargin=True)

#fig_bytes = fig.to_image(format='png')
buffer = fig.to_image(format='svg').decode("utf-8")
# Create plot and write it into the buffer

# The output is the content of the buffer
output_image = b'<?xml version="1.0" encoding="utf-8" standalone="no"?>\r\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"\r\n  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\r\n'.decode("utf-8") + buffer



1 Like

Hi @vincent_m,

Sorry for the late reply. Replacing the last two lines of actual code by this seems to work for me:

buffer = fig.to_image(format='svg')
output_image = b'<?xml version="1.0" encoding="utf-8" standalone="no"?>\r\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"\r\n  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\r\n' + buffer

There is no decode necessary since buffer and the <?xml... byte string both already contain bytes rather than characters.

Marcel

1 Like

Hi @MarcelW

Thank you very much, for your answer. You saved my life.
I don’t wanto be annoying, but I have a last question about this. As you said, with your code, I indeed have an active outport image. But here is a thing, we don’t have a true svg as outport image, don’t we ?
I mean, it seems like Knime understands it as a png or something like that. Is there a way to get a svg in outport as one as we can get with plotly in Generic JavaScript View ?
Thank you very much

Hi @vincent_m,

Glad to hear that this worked so far! :slight_smile:

I am afraid I do not fully understand what a “true” SVG would look like to you (but I have never used the Generic JavaScript View, so I am probably missing the comparison). If you append the Image to Table node to the Python node, execute it, open its output table, and set the renderer of the Image column to XML (right click on the column header > Available Renderers > XML Document), you will see that it is an SVG image. KNIME of course renders it to a raster graphic for display purposes, maybe the JavaScript node does this differently?

Marcel

Hi @MarcelW,

Once again, thank you for your help. I mean, Generic Javascript view, or some integrated data visualisation nodes in Knime, render an interactive svg file.
And so, it would be absolutely awesome for me to have a way with python to get as outport an interactive SVG too (handling mouse events).
Do you know how I could do this ?

Thank you very much,

Vincent

Hi @vincent_m,

I see – no, the Python View node unfortunately does not offer an interactive view.
If you feel comfortable using the Generic JavaScript View, maybe you could display the SVG generated by the Python node in an interactive view there. Just a rough sketch:

  1. Append an Image to Table node to the Python View node
  2. Append a Generic JavaScript View node to the Image to Table node
  3. In the JavaScript node, the SVG can be accessed like this (svg will be an SVG-formatted string):
    let svg = knimeDataTable.getRows()[0].data[0];
    
  4. Embed the SVG in the document or pass it to a library. I honestly do not know what would be the best thing to do here since I do not really use JavaScript myself, maybe someone else can help us here.

Sorry, that is the best that I could come up with. I do not think our other View nodes support displaying images generated by other nodes in an interactive way.

Marcel

2 Likes

Hi @MarcelW ,

Sorry for the late reply.
Thank you very much for your answers. You really helped me, and now my workflow is doing exactly what I want it to do :slight_smile:

3 Likes

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