mp-007 / kivy_matplotlib_widget

A fast matplotlib rendering for Kivy based on Kivy_matplotlib project and kivy scatter. Matplotlib used 'agg' backend
MIT License
33 stars 6 forks source link

Faster rendering #24

Open GvozdevLeonid opened 1 month ago

GvozdevLeonid commented 1 month ago

Do you think it's worth adding a crop factor?

We can reduce the matplotlib rendering texture, which should increase rendering speed at the expense of quality. The developer can choose the required quality reduction. It is advisable to reduce the dpi by the same crop factor. I did a little testing and in my example increased the fps by two times from 5 to 10 with crop factor 2. I have two graphs updating simultaneously 60 times per second. Unfortunately, I can't attach the modified code due to incomplete implementation. I do not use the hover effect and various other functions that use position or size.

mp-007 commented 1 month ago

Thanks for the idea. Have you try to reduce the figure dpi like this:

import matplotlib as mpl
mpl.rcParams['figure.dpi'] = 50 #default is 100

For my comprehension, if the figure is smaller, the rendering time is faster (less pixel to render).

Also, do you use these parameters for your project

#optimized draw on Agg backend
mpl.rcParams['path.simplify'] = True
mpl.rcParams['path.simplify_threshold'] = 1.0
mpl.rcParams['agg.path.chunksize'] = 1000 #you can change this parameter for better result. See matplotlib docs

When you say "reduce the matplotlib rendering texture", do you have a function for that?

GvozdevLeonid commented 1 month ago

I set 120 dpi as default

matplotlib.rcParams['figure.dpi'] = 120

then I added new property

class MatplotFigure(Widget):
    ...
    crop_factor = NumericProperty(2)

    def on_figure(self, obj, value):
        self.figure.dpi = 120 / self.crop_factor

    def _onSize(self, o, size):
        dpival = self.figure.dpi
        winch = self._width / dpival
        hinch = self._height / dpival

        self.figure.set_size_inches(winch / self.crop_factor, hinch / self.crop_factor)

Now our image will be really reduced by half and the rendering speed will be increased.

But it seems that this also requires changing all events (my personal example)

    def on_mouseover(self, window, pos):
        trans = self.axes.transData.inverted()
        x, y = trans.transform_point(((pos[0] - self.pos[0]) / self.crop_factor, (pos[1] - self.pos[1]) / self.crop_factor))

When I changed the dpi in matplotlib the rendering speed did not change. It looks like a zoom change

mp-007 commented 1 month ago

Very interesting. I think it will be good to have this option. First I think we should have a new widget with only the pan and the zoom option. Just to be sure that everything it's working correctly. Feel free to create a PR if you can. Otherwise, I can work on it when I have time. I'm more busy presently.