1

I am trying to access the axis label strings for my plot in matplotlib so that I can then create a new set of them. However, whenever I try to get them with axes.get_xticklabels(), I only get an empty string in return. I read that the labels are only populated after a draw() method is called, but calling pyplot.draw() does nothing here.

ax=0
for i in yvar:
    hist00, ext00, asp00 = histogram(np.log10(df[spn[xvar]]), np.log10(df[spn[i]]), 100, False)
    axes[ax].imshow(hist00, norm = matplotlib.colors.LogNorm(), extent = ext00, aspect = asp00) 
# This first part of the code just has to do with my custom plot, so I don't think it should affect the problem.

    plt.draw() # Calling this to attempt to populate the labels.
    
    for item in axes[ax].get_xticklabels():
        print(item.get_text()) # Printing out each label as a test
    
    ax +=1 # The axes thing is for my multi-plot figure.

The labels show up normally when I show() the plot, or when I save it. But the code above only prints empty strings. I also tried to access the labels after the loop, but it still didn't work.

The weirdest part of this is that if I remove the looping part and put in i = 0, then it works if I paste it into python interactive terminal line by line, but not if I run the script... This part is confusing but not as important.

What is the problem with my code? Is there something else I need to do for this?

This is a follow-on from my previous question, which didn't get much traction. Hopefully this is more approachable.

1
  • matplotlib online creates the tick labels at the last moment, just before plotting. It is only when the last elements have been added to the plot that the exact extent is known and positions can be calculated. Commented Oct 25, 2021 at 23:00

1 Answer 1

2

Looking at the documentation for plt.draw(), you can see that it really just calls gcf.canvas.draw_idle(), which "schedules a rendering the next time the GUI window is going to re-paint the screen". If we look at the source for gcf.canvas.draw_idle you can see that it just calls gcf.canvas.draw under certain conditions.

Instead, if you use fig.canvas.draw(), you should get what you are looking for as this will force the figure to be drawn. In fact, if you look at the documentation, you will see that this function renders the figure and "walk[s] the artist tree even if not output is produced because this will trigger deferred work (like computing limits auto-limits and tick values)"

Thus the code below should do what you are looking for.

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = plt.axes([0.1, 0.1, 0.8, 0.8])
ax.plot(np.random.random(100), '.')

fig.canvas.draw() # <---- This is the line you need

print(ax.get_xticklabels())
# [Text(-20.0, 0, '-20'), Text(0.0, 0, '0'), Text(20.0, 0, '20'), Text(40.0, 0, '40'), Text(60.0, 0, '60'), Text(80.0, 0, '80'), Text(100.0, 0, '100'), Text(120.0, 0, '120')]

As a closing note, the documentation also notes that most of the time, gcf.canvas.draw_idle is preferable to gcf.canvas.draw to reduce time spent rendering figures unnecessarily.

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

2 Comments

This seems to work, thank you! I still don't know why it worked occasionally sometimes earlier, but that isn't as important.
@syzygy350, I updated the answer, hopefully this helps to explain why. Not sure of the exact conditions underwhich draw_idle would do what you need but as noted above, it plt.draw calls gcf.canvas.draw_idle which calls gcf.canvas.draw under certain conditions.

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.