5

I have figured out how to make a matplotlib graph clickable so that I can click a point and create a new plot based off of metadata for that point, following the answer here.

Now it comes time to put that clickable plot in a Panel dashboard. The obvious move is to add that figure to a panel.Row. While this displays the figure, I do not get the interactivity.

import matplotlib.pyplot as plt
import panel as pn

class custom_objects_to_plot:
    def __init__(self, x, y, name):
        self.x = x
        self.y = y
        self.name = name

a = custom_objects_to_plot(10, 20, "a")
b = custom_objects_to_plot(30, 5, "b")
c = custom_objects_to_plot(40, 30, "c")
d = custom_objects_to_plot(120, 10, "d")

def on_pick(event):
    my_fig, my_ax = plt.subplots() # New plot with unique name
    my_ax.scatter([1, 2, 3, 4], [5, 6, 7, 8]) # Make the scatterplot
    my_fig.show() # Show the plot

fig, ax = plt.subplots()
for obj in [a, b, c, d]:
    artist = ax.plot(obj.x, obj.y, 'ro', picker=5)[0]
    artist.obj = obj

fig.canvas.callbacks.connect('pick_event', on_pick)

my_row = pn.Row()
my_row.append(fig)
my_row.show()

How would I get the interactive (clickable) plot to appear like how it appears when I run from the command line?

Dave
  • 314
  • 2
  • 13

1 Answers1

1

I am not too familiar with panel, but I found this open issue on their git:

https://github.com/holoviz/panel/issues/2349

The issue states:

I like to build interactive GUIs with matplotlib with heavy usage of matplotlibs events e.g button_press_event, motion_notify_event etc. Currently this is not possible in Panel as Matplotlib is pretty much handled as a static image that can be redrawn when it's object changes.

I also checked the docs, along with a couple new updates to the open issue, and it looks like there's some functionality added via ipympl where you can use an interactive back-end, but I don't know how fleshed out it is. I'd assume it'll look something like this, but I can test it later tonight.

fig.canvas.callbacks.connect('pick_event', on_pick)

mpl_pane = pn.pane.Matplotlib(fig, interactive=True)
my_row = pn.Row(mpl_pane)
my_row.show()

Just curious, but does it have to use panel, or will another python GUI work? I know how to do this in other python GUI frameworks.

jhp
  • 61
  • 2
  • 1
    I suppose it does not have to be `panel`. What else did you have in mind? I do need to produce the graphs using `matplotlib`, however. – Dave Oct 26 '21 at 15:05
  • 1
    I tried out your four lines of `panel` code, and it did not work. In fact, `help(pn.pane.Matplotlib)` does not show an `interactive` argument, though that does not crash my code. Thoughts? If you can tweak those lines to get it to work, that would help me immensely. – Dave Oct 26 '21 at 15:23
  • Ok, this is totally silly, but I swapped backends by running `jupyter-run script.py` instead of `python3 script.py`, adding `%matplotlib` after imports, and it worked? I decided to look into it a bit more, and while running the script, I realized that (at least for me) it starts a bokeh/tornado server, exports the plot as a .png, then displays it. I decided to try and run the backend via jupyter, and that worked. I'm not totally satisfied with that answer, because I think it's likely possible to do or force without jupyter, so I'm kind of curious now and I'll check it out a bit more tomorrow. – jhp Oct 26 '21 at 23:00
  • to clarify: I used your exact code with `%matplotlib` as the only line added after the imports. I then ran `python3 -m jupyter run script.py`. I'm still going to check out the back end, but I figured I'd add that too! – jhp Oct 26 '21 at 23:22
  • 1
    And it gave you the interactivity? How? Did it open a new tab in the browser where the original `panel` graph is? // I, too, have a tornado server start up, and this has happened on multiple computers. // This isn't quite working for me, though I am not on the computer right now where it has to work. Nonetheless, you've been trying to help and are continuing, so congrats on the bounty! – Dave Oct 26 '21 at 23:47
  • Thanks, and I think I figured it out! Source code for panel: https://github.com/holoviz/panel/blob/1a334dce8b482e0ef41f17a2297ad26fa09d621f/panel/pane/plot.py#L128 by default, it converts your plot into a .png to make easier to display in a browser. However, they use a jupyter backend (ipympl) for interactive mode. I had trouble running their example in the provided widget, and I expect that our versions of panel are a bit out of date, but I can also do this via a custom widget with whatever version(s) are in pip. It'll take me maybe an hour or so, but I'll try it out in a little bit :)! – jhp Oct 27 '21 at 22:53
  • Sorry for the delay! I got caught up with items at work. I'll post code tonight. – jhp Nov 04 '21 at 21:37