1

I know there are other people asking this question in their specific context, but none of those answers have gotten me closer to figuring this out. I am trying to use a class in matplotlib to add plots to a figure.

I'm trying to get the class to take as an argument a Line2D object and interpret it a bit - this is working. The class also registers a callback to mouse click events on the plot window - this is also working. Here's what's not working:

fig, ax = plt.subplots()
series, = ax.plot(x_data, y_data)
classthing = MyClass(series)
plt.show()

And here is the class that is being instanced:

class MyClass:
    def __init__(self, series):
        self.series = series
        self.cid = series.figure.canvas.mpl_connect('button_press_event', self)

    def __call__(self, event):
        self.series.figure.plot([xdata], [ydata])  
        self.series.figure.canvas.draw()

On mouse click I want to add a plot to the figure that I clicked on. This is really similar to the example here: https://matplotlib.org/users/event_handling.html

This code successfully creates the plot and the object, but obviously I'm not calling the plot() method from the correct reference since I get the title error on the second to last line. How can I reference the plot object properly given only the Line2D object that is in it? I am not anywhere near competent with OOP.

Thanks in advance for your help.

1
  • You don't plot on figures. You plot on axes that live in figures. Commented Oct 24, 2018 at 21:50

1 Answer 1

1

You can't both plot an ax and use it again. The series in your code is a Line2D Object, which doesn't have an attribute plot.

What you can do is to add a ax object to your Class like this:

class MyClass:
    def __init__(self, series, fig):
        self.series = series
        self.figure = fig
        self.cid = self.figure.canvas.mpl_connect('button_press_event', self)

    def __call__(self, event):
        self.series.plot([xdata], [ydata])  
        self.figure.canvas.draw()

fig, ax = plt.subplots()
series = ax
classthing = MyClass(series)
classthing(some_event) # call your class

Now since you're passing an ax to the class your call will be successful, you still need to pass xdata and ydata to your call, though.

Since you'll be calling figure due to canvas draws, you'll need to pass that into your object as well.

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

2 Comments

Thanks for your reply - I was able to get it working by just passing ax into the class. There's a lot I'm not getting about how event-oriented Python works. The purpose of this class is to gather some input data from the user before continuing to execute, but right now the script just finishes immediately even while the class waits for input. I need to find out how to force my script to wait for the callback to be completed x times, but I suppose that's another question.
Try async - but this would be a much larger subject

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.