0

I'm looking to implement this MWE:

https://stackoverflow.com/a/44922317/6924364

But with Gnuplot, similar to this:

https://stackoverflow.com/a/21633082/6924364

How can I pass the Gnuplot output to the Kivy app, and display the image without having to save it locally?


Edit 1: Here is a MWE that just requires some code to add the image object to a custom widget, but I'm not sure how to accomplish that.

from subprocess import Popen, PIPE
from StringIO import StringIO                                            
from io import BytesIO
from os import linesep as nl
from PIL import Image as Image

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.core.image import Image as CoreImage


def gnuplot(commands, data):                                                    
    """ drive gnuplot, expects lists, returns stdout as string """              

    dfile = StringIO()                                                          
    for line in data:                                                           
        dfile.write(str(line) + nl)                                             

    args = ["gnuplot", "-e", (";".join([str(c) for c in commands]))]            
    p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)                       

    dfile.seek(0)                                                               
    return p.communicate(dfile.read())[0]   


def gnuplot_GifTest():
    commands = [\
        "set datafile separator ','",\
        "set terminal png",\
        "set output",\
        "plot '-' using 1:2 with linespoints, '' using 1:2 with linespoints",\
        ]
    data = [\
        "1,1",\
        "2,2",\
        "3,5",\
        "4,2",\
        "5,1",\
        "e",\
        "1,5",\
        "2,4",\
        "3,1",\
        "4,4",\
        "5,5",\
        "e",\
        ]

    return (commands, data)


class Plot(Widget):

    (commands, data) = gnuplot_GifTest()
    img = BytesIO(gnuplot(commands,data))
    anImg = CoreImage(img,ext="png")

    def __init__(self,**kwargs):
        super(Plot,self).__init__(**kwargs)

        # HMM, how to display self.anImg??
        print self.anImg

class MyApp(App):

    def build(self):
        box = BoxLayout(orientation="vertical")
        box.add_widget(Plot())
        return box

MyApp().run()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Justapigeon
  • 560
  • 1
  • 8
  • 22
  • I've made some headway and discovered that, in the second MWE, the outputted StringIO can be converted to an object with consideration of https://stackoverflow.com/a/23489503/6924364. I'll post a full MWE integrated into kivy soon. – Justapigeon Dec 07 '18 at 18:24
  • Made more progress with this MWE: https://stackoverflow.com/a/52340135/6924364. Now, to synthesize all of this code. – Justapigeon Dec 07 '18 at 18:40
  • MWE added to the original post. – Justapigeon Dec 07 '18 at 19:48
  • I've discovered the solution! https://stackoverflow.com/a/37279624/6924364 – Justapigeon Dec 07 '18 at 21:06
  • This reference may also be relevant for future readers; I didn't replicate what was accomplished in it, but it would be cool to have a kivy lib that automates gnu plotting: https://github.com/kivy-garden/garden.matplotlib/blob/master/backend_kivyagg.py – Justapigeon Dec 07 '18 at 21:11

1 Answers1

0

After some research, I've found a solution to my problem. I'll leave this open over the weekend for other readers, should there be other solutions.

from subprocess import Popen, PIPE
from StringIO import StringIO                                            
from io import BytesIO
from os import linesep as nl
from PIL import Image as Image

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.core.image import Image as CoreImage
from kivy.uix.image import Image as UIXImage

def gnuplot(commands, data):                                                    
    """ drive gnuplot, expects lists, returns stdout as string """              

    dfile = StringIO()                                                          
    for line in data:                                                           
        dfile.write(str(line) + nl)                                             

    args = ["gnuplot", "-e", (";".join([str(c) for c in commands]))]            
    p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)                       

    dfile.seek(0)                                                               
    return p.communicate(dfile.read())[0]   


def gnuplot_GifTest():
    commands = [\
        "set datafile separator ','",\
        "set terminal gif",\
        "set output",\
        "plot '-' using 1:2 with linespoints, '' using 1:2 with linespoints",\
        ]
    data = [\
        "1,1",\
        "2,2",\
        "3,5",\
        "4,2",\
        "5,1",\
        "e",\
        "1,5",\
        "2,4",\
        "3,1",\
        "4,4",\
        "5,5",\
        "e",\
        ]

    return (commands, data)


class Plot(UIXImage):

    def __init__(self,commands,data,**kwargs):
        super(Plot,self).__init__(**kwargs)
        gnu_img = BytesIO(gnuplot(commands,data))
        gnu_converted = CoreImage(gnu_img,ext="gif")
        self.texture = gnu_converted.texture


class MyApp(App):

    def build(self):
        (commands, data) = gnuplot_GifTest() # example for passing gnuplot commands and data to the plot widget
        box = BoxLayout(orientation="vertical")
        box.add_widget(Plot(commands,data))
        return box

MyApp().run()
Justapigeon
  • 560
  • 1
  • 8
  • 22