1

I am trying to handle a list of figures with an object. Unfortunately there seems to be a problem with plotting from a list of figures.

Please comment out the line in the example below and you see how the plotting breaks:

import matplotlib as mpl
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, FigureManagerQT


class Test:
    def __init__(self):
        self.figs = [mpl.figure.Figure(),mpl.figure.Figure()]
        self.fig = mpl.figure.Figure()
        ax = self.fig.subplots()
        ax.plot([1,2],[3,4])

    def show(self):
        fig = self.fig  # works
#        fig = self.figs[0]  # does not work
        canvas = FigureCanvasQTAgg(fig)
        figManager = FigureManagerQT(canvas, 0)

a=Test()
a.show()

Result (this is what I want): enter image description here

Result with line uncommented: enter image description here

In some other tests I found it might be connected with destructing the object. As a list is a mutable object, this might be the connection. I also tried (unsuccessfully) several workarounds to copy the figure object for plotting: I used something like fig = myCopy(self.figs[0]) in combination with a pickle-copy.

Can you please give me some explanation of what is happening and what might be a workaround?

Markus Dutschke
  • 9,341
  • 4
  • 63
  • 58

1 Answers1

3

In __init__, you give axes to self.fig and plot to this Axes object:

class Test:
    def __init__(self):
        self.figs = [mpl.figure.Figure(),mpl.figure.Figure()]
        self.fig = mpl.figure.Figure()
        ax = self.fig.subplots()
        ax.plot([1,2],[3,4])

The figure objects in self.figs have no Axes object attached to them, so they're basically empty. As a result, what you see is an empty figure:

def show(self):
    fig = self.figs[0] # This is a figure with no axes
    canvas = FigureCanvasQTAgg(fig)
    figManager = FigureManagerQT(canvas, 0)

The problem with your logic is that it's not really meaningful to plot data in the __init__ method. Your workflow should be:

  1. Initialization
  2. Figure selection
  3. Plot
  4. Show

I suggest that you add two methods, select_figure and plot, so as to improve the overall usability of your figure manager:

class Test:
    def __init__(self):
        self.fig = None
        self.figures = [mpl.figure.Figure(), mpl.figure.Figure()]

    def select_figure(self, index):
        self.fig = self.figures[index]

    def plot(self, x, y):
        ax = self.fig.subplots()
        ax.plot(x, y)

    def show(self):
        canvas = FigureCanvasQTAgg(self.fig)
        figManager = FigureManagerQT(canvas, 0)

Then you can implement the workflow I described above:

test = Test()

test.select_figure(0)
test.plot([1, 2], [3, 4])
test.show()

test.select_figure(1)
test.plot([3, 4], [5, 6])
test.show()
Right leg
  • 16,080
  • 7
  • 48
  • 81
  • oh man, this is so embarrassing that I forgot to add an Axes object to my figures in my list!!! What I presented was only a minimal example (which now does not reproduce my error anymore). I will continue checking these days and come back with adjustments. – Markus Dutschke Jul 30 '19 at 14:32
  • @MarkusDutschke Haha no worries :) Don't hesitate to open a new question if you come across another issue in your code! – Right leg Jul 30 '19 at 14:34
  • ok, things got even more embarrassing, as I found the issue of my original code: I had a destructor defined and forgotten long time ago, which was responsible for the unexpected behavior. Thank you for your answer. That made me look for the simple solutions. I think the take home message here is: LOOK FOR THE VERY SIMPLE THINGS BEFORE HITTING ON THE COMPLEX. – Markus Dutschke Jul 30 '19 at 14:49