7

I have a loop which loads and plots some data, something like this:

import os
import numpy as np
import matplotlib.pyplot as plt

for filename in filenames:
    plt.figure()
    if os.path.exists(filename):
        x, y = np.loadtxt(filename, unpack=True)
        plt.plot(x, y)
    plt.savefig(filename + '.png')
    plt.close()

Now, if the file does not exist, the data is not loaded or plotted but an (empty) figure is still saved. In the above example I could correct for this simply by including all of the plt calls inside of the if statement. My real use case is somewhat more involved, and so I am in search for a way to ask matplotlib/plt/the figure/the axis whether or not the figure/axis is completely empty or not. Something like

for filename in filenames:
    plt.figure()
    if os.path.exists(filename):
        x, y = np.loadtxt(filename, unpack=True)
        plt.plot(x, y)
    if not plt.figure_empty():  # <-- new line
        plt.savefig(filename + '.png')
    plt.close()
jmd_dk
  • 12,125
  • 9
  • 63
  • 94
  • 1
    Note that there is never a completely empty figure. So you may want to define "empty" a bit more thorough. Also any information you may have on what non-empty figures might contain is probably helpful, e.g. if you knew e.g. that if a figure is to be considered as "non-empty" it would contain one line in one axes, or two images or similar, that would allow to test against those in particular. – ImportanceOfBeingErnest Sep 18 '18 at 13:15

3 Answers3

11

To check if an ax has data drawn using plot():

if ax.lines:

If they were drawn using scatter() instead:

if ax.collections:
Guimoute
  • 4,407
  • 3
  • 12
  • 28
  • 1
    If drawn using `imshow` check the list output from `ax.get_images()`. In action you can use it through `if bool(ax.get_images()):` – Aelius Nov 04 '21 at 12:11
  • 1
    @Aelius Absolutely. There are many lists that we can check. We can also check [`if ax.hasData()`](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.has_data.html#matplotlib.axes.Axes.has_data) that returns true if at least one artist (of any type) is found. – Guimoute Nov 04 '21 at 19:22
  • Wonderful! I wasn't aware of that...the matplotlib.axes page is not well documented for what regards the methods – Aelius Nov 05 '21 at 09:09
  • 1
    Great tipp @Guimoute, just the method is named [has_data()](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.has_data.html) not hasData() (but the linkdoes point to the right page in the docs). – Johannes Schöck Feb 04 '22 at 13:57
2

Does checking whether there are any axes in the figure with fig.get_axes() work for your purposes?

fig = plt.figure()
if fig.get_axes():
    # Do stuff when the figure isn't empty.
Denziloe
  • 7,473
  • 3
  • 24
  • 34
1

As you say, the obvious solution is to include saving within the if statement

for filename in filenames:
    plt.figure()
    if os.path.exists(filename):
        x, y = np.loadtxt(filename, unpack=True)
        plt.plot(x, y)
        plt.savefig(filename + '.png')  # <-- indentation here
    plt.close()

Else, it will depend on what "empty" really means. If it is that a figure does not contain any axes,

for filename in filenames:
    fig = plt.figure()
    if os.path.exists(filename):
        x, y = np.loadtxt(filename, unpack=True)
        plt.plot(x, y)
    if len(fig.axes) > 0:  
        plt.savefig(filename + '.png')
    plt.close()

However those are somehow workarounds. I think you really want to perform the logic step yourself.

for filename in filenames:
    plt.figure()
    save_this = False
    if os.path.exists(filename):
        x, y = np.loadtxt(filename, unpack=True)
        plt.plot(x, y)
        save_this = True
    if save_this:
        plt.savefig(filename + '.png')
    plt.close()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • In your last case, let's say x and y are empty (no data in the file), still a blank figure will be generated and `save_this` will become `True` and hence the figure will be saved. Or am I missing something in OP's question? – Sheldore Sep 18 '18 at 12:51
  • `if fig.axes:` is a bit more Pythonic. – Denziloe Sep 18 '18 at 12:51
  • @Bazingaa an empty file would raise an error. But that's the point: We cannot know anything about the conditions under which a figure shall be saved or not, hence the OP would want to set this condition to his liking. – ImportanceOfBeingErnest Sep 18 '18 at 13:02
  • @ImportanceOfBeingErnest: If I try to save an empty plot I get no error. But to make raise an error, one would need to apply some checks on the input data shape/len. Anyway, since the OP's problem is not very clear, makes no point further clarifying. Thanks for the reply though – Sheldore Sep 18 '18 at 13:08
  • @Bazingaa The line `x, y = np.loadtxt(filename, unpack=True)` would raise an error if `filename` was an empty file. So either the file exists and has some data in it, then the figure is saved, or the file does not exist,then it is not saved. If it was possible for the file to be empty, the code would need to look different anyways (possibly using try/except). – ImportanceOfBeingErnest Sep 18 '18 at 13:11
  • Got it. Thanks :) – Sheldore Sep 18 '18 at 13:13