kivy-garden / graph

Displays plots on a graph.
MIT License
50 stars 19 forks source link

Bar width in BarPlot is decreasing with increasing xmin #35

Open ma3xxx3 opened 1 week ago

ma3xxx3 commented 1 week ago

Describe the bug Bar width in BarPlot is decreasing with increasing xmin of graph, even when xmin - xmax range is constant: BarPlot

To Reproduce Update xmin and xmax and BarPlot points range in example code in main

#............
            graph = Graph(
                xlabel='Cheese',
                ylabel='Apples',
                x_ticks_minor=5,
                x_ticks_major=25,
                y_ticks_major=1,
                y_grid_label=True,
                x_grid_label=True,
                padding=5,
                xlog=False,
                ylog=False,
                x_grid=True,
                y_grid=True,
                xmin=150,   
                xmax=200, 
                ymin=-1,
                ymax=1,
                **graph_theme)

#............

            plot = BarPlot(color=next(colors), bar_spacing=.72)
            graph.add_plot(plot)
            plot.bind_to_graph(graph)
            plot.points = [(x, .1 + randrange(10) / 10.) for x in range(150, 200)]

#............

Expected behavior Bar width should be constant if xmin - xmax range is not changing.

Platform (please complete the following information):

mp-007 commented 1 week ago

@ma3xxx3 maybe off topic, but it is not easier with matplotlib? Why not using kivy_matplotlib_widget https://github.com/mp-007/kivy_matplotlib_widget. The drawing should fast enough for your purpose.

ma3xxx3 commented 1 week ago

@mp-007 thanks, could be intersting. I found this issue during playing with some additional interactive functions like zoom and move. BTW.: I should have already fix, will create pull request. Finally I would like to use quite big data and my own plot based on BarPlot. I need big interactive gantt chart.

mp-007 commented 1 week ago

I did this with my widget and the FPS still correct on my PC (no lag). Also you can have a hover and a pan_x if you want for your barplot. Anyway, use the best widget for your case.

https://github.com/user-attachments/assets/dadbdd10-42be-4e53-9997-01ac28c1c045

This is my code

from kivy.app import App
from kivy.lang import Builder
import kivy_matplotlib_widget #registers all widgets in kivy factory
from matplotlib import pyplot as plt

import pandas as pd
import numpy as np

KV = '''
Screen
    figure_wgt:figure_wgt
    BoxLayout:
        orientation:'vertical'
        BoxLayout:
            size_hint_y:0.2
            Button:
                text:"home"
                on_release:app.home()
            ToggleButton:
                group:'touch_mode'
                state:'down'
                text:"pan" 
                on_press:
                    app.set_touch_mode('pan')
                    self.state='down'
            ToggleButton:
                group:'touch_mode'
                text:"zoom box"  
                on_press:
                    app.set_touch_mode('zoombox')
                    self.state='down'  

        MatplotFigureSubplot:
            id:figure_wgt
            fast_draw:True
'''

def activate_monitor_mode():
    """Activate kivy monitor mode (get fps rate information in top bar)"""
    from kivy.core.window import Window
    from kivy.modules import Modules
    from kivy.config import Config

    Config.set('modules', 'monitor', '')        
    Modules.activate_module('monitor',Window)

class uiApp(App):
    def build(self):
        self.screen=Builder.load_string(KV)
        return self.screen

    def on_start(self, *args):
        activate_monitor_mode()
        # Plotting the aggregated data
        np.random.seed(0)
        data = pd.DataFrame(np.random.rand(1, 100), columns=[f"Col_{i}" for i in range(100)])

        # Bar plot configuration
        fig=plt.figure(figsize=(20, 8))  # Increase figure size to fit columns
        data.iloc[0].plot(kind='bar', width=0.8)

        # Rotate labels for better readability
        plt.xticks(rotation=90, fontsize=8)
        plt.xlabel("Columns")
        plt.ylabel("Values")
        plt.title("Bar Plot with Many Columns")

        self.screen.figure_wgt.figure =fig 

    def home(self):
       self.screen.figure_wgt.home()

    def set_touch_mode(self,mode):
        self.screen.figure_wgt.touch_mode=mode

uiApp().run()