kivy/kivy-ios

Matplotlib gets app freezing while uploading on phone

causeri3 opened this issue · 7 comments

I can't get kivy running on my ios device with matplotlib. It freezes on my phone while I see the uploading screen.

MRE

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.graphics.texture import Texture
from kivy.graphics import Rectangle
import os
import numpy as np



class MatplotlibWidget(Widget):
    def __init__(self, **kwargs):
        super(MatplotlibWidget, self).__init__(**kwargs)

        app = App.get_running_app()
        os.environ['MPLCONFIGDIR'] = app.user_data_dir
        import matplotlib.pyplot as plt

        x = np.linspace(0, 10, 100)
        y = np.sin(x)

        fig, ax = plt.subplots()
        ax.plot(x, y, label='sin(x)')
        ax.set_xlabel('x')
        ax.set_ylabel('sin(x)')

        self.temp_file = os.path.join(app.user_data_dir, 'temp_plot.png')
        fig.savefig(self.temp_file)

        texture = Texture.create(size=(fig.get_figwidth() * 100, fig.get_figheight() * 100))
        texture.flip_vertical()
        texture.blit_buffer(fig.canvas.tostring_rgb(), colorfmt='rgb', bufferfmt='ubyte')

        with self.canvas:
            Rectangle(texture=texture, size=(fig.get_figwidth() * 100, fig.get_figheight() * 100), pos=self.pos)

        plt.close(fig)


class MatplotlibApp(App):


    def build(self):
        print("app.directory = ", self.directory)
        print("app.user_data_dir = ", self.user_data_dir)
        layout = BoxLayout()

        layout.add_widget(MatplotlibWidget())

        return layout


if __name__ == '__main__':
    MatplotlibApp().run()

My setup

  • Sonoma 14.3.1
  • iOS 17.3.1
  • Kivy==2.3.0
  • kivy-ios==2024.3.17

Running

brew install autoconf automake libtool pkg-config
brew link libtool
pip3 install Cython==3.0.0
toolchain build kivy
toolchain build matplotlib
toolchain create mat matplot-kivy-test
toolchain update mat-ios

XCode gives me:

Available orientation: KIVY_ORIENTATION=LandscapeLeft LandscapeRight Portrait PortraitUpsideDown
Initializing python
:1: DeprecationWarning: the imp module is deprecated in favour of importlib and slated for removal in Python 3.12; see the module's documentation for alternative uses
Running main.py: /private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/YourApp/main.pyc
[INFO ] [Logger ] Record log in /private/var/mobile/Containers/Data/Application/6274477B-265C-402E-B79F-9FCDEE0EA66F/Documents/.kivy/logs/kivy_24-03-25_7.txt
[INFO ] [Kivy ] v2.3.0
[INFO ] [Kivy ] Installed at "/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/kivy/init.py"
[INFO ] [Python ] v3.11.6 (main, Mar 25 2024, 09:45:57) [Clang 15.0.0 (clang-1500.1.0.2.5)]
[INFO ] [Python ] Interpreter at "/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/mat"
[INFO ] [Logger ] Purge log fired. Processing...
[INFO ] [Logger ] Purge finished!
[INFO ] [Factory ] 195 symbols loaded
[INFO ] [Image ] Providers: img_imageio, img_tex, img_sdl2 (img_dds, img_ffpyplayer, img_pil ignored)
app.directory = /private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/YourApp
app.user_data_dir = /private/var/mobile/Containers/Data/Application/6274477B-265C-402E-B79F-9FCDEE0EA66F/Documents/matplotlib
[INFO ] [Window ] Provider: sdl2
You need UIApplicationSupportsIndirectInputEvents in your Info.plist for mouse support
[INFO ] [GL ] Using the "OpenGL ES 2" graphics system
[INFO ] [GL ] Backend used
[INFO ] [GL ] OpenGL version <b'OpenGL ES 2.0 Metal - 99'>
[INFO ] [GL ] OpenGL vendor <b'Apple Inc.'>
[INFO ] [GL ] OpenGL renderer <b'Apple A16 GPU'>
[INFO ] [GL ] OpenGL parsed version: 2, 0
[INFO ] [GL ] Shading version <b'OpenGL ES GLSL ES 1.00'>
[INFO ] [GL ] Texture max size <4096>
[INFO ] [GL ] Texture max units <8>
[INFO ] [Window ] auto add sdl2 input provider
[INFO ] [Window ] virtual keyboard not allowed, single mode, not docked
[DEBUG ] [matplotlib data path] /private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data
[DEBUG ] CONFIGDIR=/private/var/mobile/Containers/Data/Application/6274477B-265C-402E-B79F-9FCDEE0EA66F/Documents/matplotlib
[DEBUG ] interactive is False
[DEBUG ] platform is ios
[DEBUG ] CACHEDIR=/private/var/mobile/Containers/Data/Application/6274477B-265C-402E-B79F-9FCDEE0EA66F/Documents/matplotlib
[DEBUG ] Using fontManager instance from /private/var/mobile/Containers/Data/Application/6274477B-265C-402E-B79F-9FCDEE0EA66F/Documents/matplotlib/fontlist-v330.json
[DEBUG ] Loaded backend agg version v2.2.
[DEBUG ] [findfont ] Matching sans-serif:style=normal:variant=normal:weight=normal:stretch=normal:size=10.0.
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif.ttf', name='DejaVu Serif', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXSizOneSymBol.ttf', name='STIXSizeOneSym', style='normal', variant='normal', weight=700, stretch='normal', size='scalable')) = 10.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif-Italic.ttf', name='DejaVu Serif', style='italic', variant='normal', weight=400, stretch='normal', size='scalable')) = 11.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymBol.ttf', name='STIXSizeTwoSym', style='normal', variant='normal', weight=700, stretch='normal', size='scalable')) = 10.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXNonUniBolIta.ttf', name='STIXNonUnicode', style='italic', variant='normal', weight=700, stretch='normal', size='scalable')) = 11.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneral.ttf', name='STIXGeneral', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXSizFourSymReg.ttf', name='STIXSizeFourSym', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXSizFiveSymReg.ttf', name='STIXSizeFiveSym', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/cmr10.ttf', name='cmr10', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymReg.ttf', name='STIXSizeThreeSym', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymBol.ttf', name='STIXSizeThreeSym', style='normal', variant='normal', weight=700, stretch='normal', size='scalable')) = 10.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans-Bold.ttf', name='DejaVu Sans', style='normal', variant='normal', weight=700, stretch='normal', size='scalable')) = 0.33499999999999996
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-Oblique.ttf', name='DejaVu Sans Mono', style='oblique', variant='normal', weight=400, stretch='normal', size='scalable')) = 11.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXSizOneSymReg.ttf', name='STIXSizeOneSym', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymReg.ttf', name='STIXSizeTwoSym', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-Bold.ttf', name='DejaVu Sans Mono', style='normal', variant='normal', weight=700, stretch='normal', size='scalable')) = 10.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-BoldOblique.ttf', name='DejaVu Sans Mono', style='oblique', variant='normal', weight=700, stretch='normal', size='scalable')) = 11.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSansMono.ttf', name='DejaVu Sans Mono', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif-BoldItalic.ttf', name='DejaVu Serif', style='italic', variant='normal', weight=700, stretch='normal', size='scalable')) = 11.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/cmss10.ttf', name='cmss10', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/cmmi10.ttf', name='cmmi10', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/cmex10.ttf', name='cmex10', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/cmtt10.ttf', name='cmtt10', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXSizFourSymBol.ttf', name='STIXSizeFourSym', style='normal', variant='normal', weight=700, stretch='normal', size='scalable')) = 10.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf', name='DejaVu Sans', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 0.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXNonUniIta.ttf', name='STIXNonUnicode', style='italic', variant='normal', weight=400, stretch='normal', size='scalable')) = 11.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXNonUniBol.ttf', name='STIXNonUnicode', style='normal', variant='normal', weight=700, stretch='normal', size='scalable')) = 10.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif-Bold.ttf', name='DejaVu Serif', style='normal', variant='normal', weight=700, stretch='normal', size='scalable')) = 10.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/cmsy10.ttf', name='cmsy10', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneralBolIta.ttf', name='STIXGeneral', style='italic', variant='normal', weight=700, stretch='normal', size='scalable')) = 11.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans-Oblique.ttf', name='DejaVu Sans', style='oblique', variant='normal', weight=400, stretch='normal', size='scalable')) = 1.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneralBol.ttf', name='STIXGeneral', style='normal', variant='normal', weight=700, stretch='normal', size='scalable')) = 10.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans-BoldOblique.ttf', name='DejaVu Sans', style='oblique', variant='normal', weight=700, stretch='normal', size='scalable')) = 1.335
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneralItalic.ttf', name='STIXGeneral', style='italic', variant='normal', weight=400, stretch='normal', size='scalable')) = 11.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSansDisplay.ttf', name='DejaVu Sans Display', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/STIXNonUni.ttf', name='STIXNonUnicode', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/cmb10.ttf', name='cmb10', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] score(FontEntry(fname='/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerifDisplay.ttf', name='DejaVu Serif Display', style='normal', variant='normal', weight=400, stretch='normal', size='scalable')) = 10.05
[DEBUG ] [findfont ] Matching sans-serif:style=normal:variant=normal:weight=normal:stretch=normal:size=10.0 to DejaVu Sans ('/private/var/containers/Bundle/Application/9BA1E625-5E54-42C1-B55F-0CBF1EE8BF8A/mat.app/lib/python3.11/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf') with score of 0.050000.

@tcaduser Could you possibly share some working code you used to develop the recipe?

Matplotlib Compatibility:
Matplotlib is primarily designed for desktop environments and might not have full compatibility with iOS.
Limited Graphics Acceleration:
Kivy on iOS relies on OpenGL for rendering, but some features like Matplotlib plots might not be efficiently handled by the limited OpenGL support on iOS devices.

mp-007 commented

@causeri3 Can you try my project if it solve your issue: https://github.com/mp-007/kivy_matplotlib_widget
My project used an other approach by using Agg backend. The rendering will be much faster.

You can used this working example:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
import os
import numpy as np
import matplotlib.pyplot as plt
from kivy_matplotlib_widget.uix.graph_widget import MatplotFigure

#or use this widget if you have multiple axis and not just lines
#from kivy_matplotlib_widget.uix.graph_subplot_widget import MatplotFigureSubplot


class MatplotlibApp(App):


    def build(self):
        print("app.directory = ", self.directory)
        print("app.user_data_dir = ", self.user_data_dir)
        layout = BoxLayout()

        x = np.linspace(0, 10, 100)
        y = np.sin(x)

        fig, ax = plt.subplots()
        ax.plot(x, y, label='sin(x)')
        ax.set_xlabel('x')
        ax.set_ylabel('sin(x)')
        
        figure_widget = MatplotFigure()
        figure_widget.figure = fig
        
        layout.add_widget(figure_widget)

        return layout


if __name__ == '__main__':
    MatplotlibApp().run()

Can you run with the xcode debugger attached to your iphone and see if it crashes in the c code. I haven't worked with this recently, but I have had issues where I have needed to compile multiple times to get the code in a good state. I think there may be some caching issue between the IOS phone and phone simulator builds.

Please see here for a brief description of what I am encountering.

#865

Will try later, right now https://download.savannah.gnu.org seems to be down.

Tbh, I gave up on matplotlib and visualize the data simplified with kivy widgets. The old XCode debugging logs from the build on my iPhone are above. For the moment, I keep on struggeling to get the App on TestFlight.