Skip to content

Convert any matplotlib figure with 1 function

Convert any matplotlib 2D figure into kivy interactive graph with only 2 lines in your ipython console

from kivy_matplotlib_widget.tools.interactive_converter import interactive_graph_ipython

interactive_graph_ipython(fig) #fig is your matplotlib figure instance
Interactive_graph_ipython is used to generate kivy interactive graph directly in python interactive console (ipython) or directly in the code if you have only 1 figure. You can generate only 1 figure at a time with this function.

You can close your kivy graph (or ctrl+c) if you want to resume your code and then you can call interactive_graph_ipython again.

See interactive_converter folder in the examples for more details.

3D figure converter

For 3D figure, use this function

interactive_graph3D_ipython(fig) #fig is your matplotlib figure instance

Not blocking method (multiprocessing)

If you need to generate multiple figure with a no blocking method, please see interactive_graph and interactive_graph3D functions.

These functions use python multiprocessing method, so it's a not blocking method and several figure can be generated. Becauce it use mutiprocessing method, it need to be call with if __name__ == "__main__":.

if __name__ == "__main__": 
    interactive_graph(fig) #2D figure

    interactive_graph3D(fig) #3D figure

Other converter functions

For more control, you can use app_window and app_window3D directly. These function are used inside interactive_graph and interactive_graph3D functions.

from kivy_matplotlib_widget.tools.interactive_converter import app_window,app_window_3D

This code test differents kind of figure using these functions. To make this code work, create a .py file and run this code. Thanks to mz3r0

import multiprocessing
import matplotlib.pyplot as plt
from kivy_matplotlib_widget.tools.interactive_converter import app_window,app_window_3D
import numpy as np

def generate_plot(kwargs):
    """Function to generate and display the plot."""
    num = kwargs['num']
    if num == 1:
        # 1. Line Plot (1D)
        x = np.linspace(0, 10, 100)
        y = np.sin(x)
        plt.figure()
        plt.plot(x, y)
        plt.title("Line Plot")
        app_window(plt.gcf())
    elif num == 2:
        # 2. Scatter Plot (2D)
        x = np.random.rand(100)
        y = np.random.rand(100)
        plt.figure()
        plt.scatter(x, y)
        plt.title("Scatter Plot")
        app_window(plt.gcf())
    elif num == 3:
        # 3. 3D Scatter Plot (3D using color for 3rd dimension)
        x = np.random.rand(100)
        y = np.random.rand(100)
        z = np.random.rand(100)
        plt.figure()
        plt.scatter(x, y, c=z, cmap='viridis')
        plt.colorbar(label="Z-axis (color)")
        plt.title("3D Scatter in 2D")
        app_window(plt.gcf(),autoscale_tight=True)
    elif num == 4:
        # 4. 4D Scatter Plot (4D with size and color for extra dimensions)
        x = np.random.rand(100)
        y = np.random.rand(100)
        z = np.random.rand(100)
        sizes = 100 * np.random.rand(100)
        plt.figure()
        plt.scatter(x, y, c=z, s=sizes, cmap='plasma', alpha=0.7)
        plt.colorbar(label="Color dimension")
        plt.title("4D Scatter in 2D")
        app_window(plt.gcf())
    elif num == 5:
        # 5. Bar Plot
        categories = ['A', 'B', 'C', 'D']
        values = [5, 7, 3, 8]
        plt.figure()
        plt.bar(categories, values)
        plt.title("Bar Plot")
        app_window(plt.gcf())
    elif num == 6:
        # 6. Histogram
        values = np.random.randn(1000)
        plt.figure()
        plt.hist(values, bins=20)
        plt.title("Histogram")
        app_window(plt.gcf())
    elif num == 7:
        # 7. Pie Chart
        sizes = [15, 30, 45, 10]
        labels = ['A', 'B', 'C', 'D']
        plt.figure()
        plt.pie(sizes, labels=labels, autopct='%1.1f%%')
        plt.title("Pie Chart")
        app_window(plt.gcf())
    elif num == 8:
        # 8. Heatmap (2D data)
        data = np.random.rand(10, 10)
        plt.figure()
        plt.imshow(data, cmap='hot', interpolation='nearest')
        plt.colorbar()
        plt.title("Heatmap")
        app_window(plt.gcf())
    elif num == 9:
        # 9. Contour Plot
        x = np.linspace(-5, 5, 100)
        y = np.linspace(-5, 5, 100)
        x, y = np.meshgrid(x, y)
        z = np.sin(np.sqrt(x ** 2 + y ** 2))
        plt.figure()
        plt.contour(x, y, z, cmap='viridis')
        plt.title("Contour Plot")
        app_window(plt.gcf(),autoscale_tight=True)
    elif num == 10:
        # 10. Box Plot
        data = [np.random.rand(50), np.random.rand(50), np.random.rand(50)]
        plt.figure()
        plt.boxplot(data)
        plt.title("Box Plot")
        app_window(plt.gcf())
    elif num == 11:
        # 11. Violin Plot
        data = [np.random.rand(50), np.random.rand(50), np.random.rand(50)]
        plt.figure()
        plt.violinplot(data)
        plt.title("Violin Plot")
        app_window(plt.gcf())
    elif num == 12:
        # 12. Step Plot
        x = np.arange(0, 10, 0.1)
        y = np.sin(x)
        plt.figure()
        plt.step(x, y)
        plt.title("Step Plot")
        app_window(plt.gcf())
    elif num == 13:
        # 13. Error Bar Plot
        x = np.linspace(0, 10, 10)
        y = np.sin(x)
        errors = 0.1 + 0.2 * np.sqrt(x)
        plt.figure()
        plt.errorbar(x, y, yerr=errors, fmt='-o')
        plt.title("Error Bar Plot")
        app_window(plt.gcf())
    elif num == 14:
        # 14. Polar Plot
        theta = np.linspace(0, 2 * np.pi, 100)
        r = 1 + np.sin(3 * theta)
        plt.figure()
        ax = plt.subplot(111, polar=True)
        ax.plot(theta, r)
        plt.title("Polar Plot")
        app_window(plt.gcf())
    elif num == 15:
        # 15. Quiver Plot
        x, y = np.meshgrid(np.arange(-2, 2, 0.5), np.arange(-2, 2, 0.5))
        u = -y
        v = x
        plt.figure()
        plt.quiver(x, y, u, v)
        plt.title("Quiver Plot")
        app_window(plt.gcf())
    elif num == 16:
        # 16. 3D Scatter Plot (3D in 3D)
        x = np.random.rand(100)
        y = np.random.rand(100)
        z = np.random.rand(100)
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')
        ax.scatter(x, y, z, c='blue')
        ax.set_title("3D Scatter in 3D")
        app_window_3D(plt.gcf())
    elif num == 17:
        # 17. 4D Scatter Plot (4D in 3D with color for 4th dimension)
        x = np.random.rand(100)
        y = np.random.rand(100)
        z = np.random.rand(100)
        c = np.random.rand(100)
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')
        p = ax.scatter(x, y, z, c=c, cmap='viridis')
        fig.colorbar(p, label="4th Dimension (color)")
        ax.set_title("4D Scatter in 3D")
        app_window_3D(plt.gcf())
    elif num == 18:
        # 18. 5D Scatter Plot (5D in 3D with color and size for extra dimensions)
        x = np.random.rand(100)
        y = np.random.rand(100)
        z = np.random.rand(100)
        c = np.random.rand(100)
        sizes = 100 * np.random.rand(100)
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')
        p = ax.scatter(x, y, z, c=c, s=sizes, cmap='plasma', alpha=0.7)
        fig.colorbar(p, label="4th Dimension (color)")
        ax.set_title("5D Scatter in 3D")
        app_window_3D(plt.gcf())


if __name__ == "__main__":
    # Set the multiprocessing start method
    multiprocessing.set_start_method("spawn")

    # Place Kivy imports here to ensure they're only in the main process
    from kivy.app import App
    from kivy.uix.button import Button
    from kivy.uix.boxlayout import BoxLayout


    class PlottingApp(App):
        def build(self):
            layout = BoxLayout(orientation="vertical")

            b1 = Button(text="1 'Line Plot'")
            b1.bind(on_press=lambda x: self.generate_plot(1))
            b2 = Button(text="2 'Scatter Plot'")
            b2.bind(on_press=lambda x: self.generate_plot(2))
            b3 = Button(text="3 '3D Scatter in 2D'")
            b3.bind(on_press=lambda x: self.generate_plot(3))
            b4 = Button(text="4 '4D Scatter in 2D'")
            b4.bind(on_press=lambda x: self.generate_plot(4))
            b5 = Button(text="5 'Bar Plot'")
            b5.bind(on_press=lambda x: self.generate_plot(5))
            b6 = Button(text="6 'Histogram'")
            b6.bind(on_press=lambda x: self.generate_plot(6))
            b7 = Button(text="7 'Pie Chart'")
            b7.bind(on_press=lambda x: self.generate_plot(7))
            b8 = Button(text="8 'Heatmap'")
            b8.bind(on_press=lambda x: self.generate_plot(8))
            b9 = Button(text="9 'Contour Plot'")
            b9.bind(on_press=lambda x: self.generate_plot(9))
            b10 = Button(text="10 'Box Plot'")
            b10.bind(on_press=lambda x: self.generate_plot(10))
            b11 = Button(text="11 'Violin Plot'")
            b11.bind(on_press=lambda x: self.generate_plot(11))
            b12 = Button(text="12 'Step Plot'")
            b12.bind(on_press=lambda x: self.generate_plot(12))
            b13 = Button(text="13 'Error Bar Plot'")
            b13.bind(on_press=lambda x: self.generate_plot(13))
            b14 = Button(text="14 'Polar Plot'")
            b14.bind(on_press=lambda x: self.generate_plot(14))
            b15 = Button(text="15 'Quiver Plot'")
            b15.bind(on_press=lambda x: self.generate_plot(15))
            b16 = Button(text="16 '3D Scatter in 3D'")
            b16.bind(on_press=lambda x: self.generate_plot(16))
            b17 = Button(text="17 '4D Scatter in 3D'")
            b17.bind(on_press=lambda x: self.generate_plot(17))
            b18 = Button(text="18 '5D Scatter in 3D'")
            b18.bind(on_press=lambda x: self.generate_plot(18))

            for b in (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18):
                layout.add_widget(b)

            return layout

        def generate_plot(self, num):
            x = [1, 2, 3, 4, 5]
            y = [i ** 2 for i in x]
            kwargs = {'data': (x, y), 'num': num}
            plot_process = multiprocessing.Process(target=generate_plot, args=(kwargs,))
            plot_process.start()
            self.plot_processes.append(plot_process)

        def on_stop(self):
            for process in self.plot_processes:
                if process.is_alive():
                    process.terminate()
            super().on_stop()

        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.plot_processes = []

    PlottingApp().run()