4

I have a stacked bar plot of analytics data embedded in my GUI which I would like to be more interactive. When the user hovers or clicks on a bar the plotted value should appear. Can this be done? I haven't been able to find anything about it in the documentation. Alternatively I could use something like PyGal but I don't know how to embed it into PyQt. Advice on either would be appreciated.

3 Answers 3

3

The easiest solution is to use matplotlib events. They work the same whether you use a standalone plotting window or embed into a GUI.

A good introduction can be found in the matplotlib manual's event handling page.

Sign up to request clarification or add additional context in comments.

2 Comments

Do you know how this would be used with this to achieve the result described in the question?
I would first suggest you update your question with an actual problem description. A problem description includes the aim (what you want to achieve), the current state (what have you done to achieve this aim), and the problem itself (what hinders you to achieve the goal). Once you've done that I (or someone else) can provide an actual answer.
1

Yes they definitely can be. The matplotlib documentation has some useful code (https://matplotlib.org/users/event_handling.html#object-picking) that you can implement in an interactive way in a qt, tk, wx etc... interface by using %matplotlib qt #tk, wx, inline#(for notebook) etc... if you run this code, i think it does something quite close to what you're after (i'm using tk... so change to qt and i'd imagine it still works). run it and then click on a point on the scatterplot to trigger the event "onpick" and show that 'point' history:

"""
compute the mean and stddev of 100 data sets and plot mean vs stddev.
When you click on one of the mu, sigma points, plot the raw data from
the dataset that generated the mean and stddev
"""
import numpy as np
import matplotlib.pyplot as plt
%matplotlib tk

X = np.random.rand(100, 1000)
xs = np.mean(X, axis=1)
ys = np.std(X, axis=1)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_title('click on point to plot time series')
line, = ax.plot(xs, ys, 'o', picker=5)  # 5 points tolerance


def onpick(event):

    if event.artist!=line: return True

    N = len(event.ind)
    if not N: return True


    figi = plt.figure()
    for subplotnum, dataind in enumerate(event.ind):
        ax = figi.add_subplot(N,1,subplotnum+1)
        ax.plot(X[dataind])
        ax.text(0.05, 0.9, 'mu=%1.3f\nsigma=%1.3f'%(xs[dataind], ys[dataind]),
                transform=ax.transAxes, va='top')
        ax.set_ylim(-0.5, 1.5)
    figi.show()
    return True

fig.canvas.mpl_connect('pick_event', onpick)

plt.show()

I don't have much experience with qt at all, but for tk it seems you can just send matplotlib figures to the canvas and they work quite well - so I assume something similar is possible in qt, but based on your question you already have it embedded and are just after the interactivity.


Head's up I ran into an issue that took a while to figure out and I don't know if it's the same in qt (maybe someone else can confirm)... but just a head's up that you may need to explicitly set picker=True when plotting. Again, I don't know really anything about qt, but here is an implementation in tk of the above, but on a custom gui where without picker=True would not be interactive:

import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure

import Tkinter as tk #for Python 3.x use import tkinter as tk
import ttk #for Python 3.x use from tkinter import ttk

class My_GUI:

    def __init__(self,master):
        self.master=master
        master.title("samplegui")
        f = Figure(figsize=(5,5), dpi=100)
        a = f.add_subplot(111)
        a.scatter(np.random.normal(size=100),np.random.normal(size=100),picker=True)
        canvas1=FigureCanvasTkAgg(f,master)
        canvas1.show()
        canvas1.get_tk_widget().pack(side="top",fill='x',expand=True)
        f.canvas.mpl_connect('pick_event',self.onpick)

        toolbar=NavigationToolbar2TkAgg(canvas1,master)
        toolbar.update()
        toolbar.pack(side='top',fill='x')

    def onpick(self,event):
        #do stuff
        print "My OnPick Event Worked!"
        return True

root=tk.Tk()
gui=My_GUI(root)
root.mainloop()

Comments

-1

To my best knowledge, not by default.

I fear, you have to work a bit for yourself, as I dont know a common widget for that. There are other QT designers which already offer more interactive plots, like: http://www.taurus-scada.org/en/latest/devel/designer_tutorial.html But, as far as I remember, it does not offer what you want. I would rather think about to create you own widget.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.