0

I've come across a number of posts such as this and this talking about how to align tick labels to avoid overlaps. In fact, the second link is basically exactly what I want to do, which is move the first and last tick (on both X and Y axis) into the plot area. Unfortunately, I'm encountering some odd behavior that I'm hoping someone can explain to me.

The code below generates 3 figures (also shown below). The first is a figure with 1 subplot, and everything works as intended. All tick labels are center-justified except the first and last on each axis, which is properly adjusted to be within the plot area.

Figure 2 has 2 subplots vertically stacked. In this plot the horizontal axis has tick labels properly justified, but on the vertical axis all the positive labels (0-10) have been justified "bottom" when only the last label (10) should have been justified "top". All others should be justified "center" still.

Figure 3 is similar to Figure 2, only with horizontally stacked subplots. In this case, it's the tick labels on the positive horizontal axis that are not correctly justified, with all labels justified "left" when only the final label should be justified "right".

Any clue why on a figure with multiple subplots the tick label justification is not being set correctly? I've made multiple versions of these plots, including embedded in a Tkinter window (my actual application) and I get the exact same result every time.

EDIT: I've added a screenshot of the plots from my actual application, which is a GUI made using Tkinter. The overall window size is 1024x768 and the plots are made using 2 figures, one for the top plot (XY) and one with two subplots for the bottom plots (XZ and YZ). This screenshot is without any resizing of the window.

import matplotlib.pyplot as plt
import matplotlib


def stylize_plot(ax=None, fig=None):
    if ax is None:
        ax = plt.gca()

    if fig is None:
        fig = plt.gcf()

    ax.axis([-10, 10, -10, 10])
    ax.grid(True)
    fig.set_tight_layout(True)
    ax.spines['left'].set_position('zero')
    ax.spines['bottom'].set_position('zero')
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    # Appears to be shifting all tick labels on positive horizontal axis for Figure with 2 subplots
    xTick_objects = ax.xaxis.get_major_ticks()
    xTick_objects[0].label1.set_horizontalalignment('left')    # left align first tick
    xTick_objects[-1].label1.set_horizontalalignment('right')  # right align last tick
    yTick_objects = ax.yaxis.get_major_ticks()
    yTick_objects[0].label1.set_verticalalignment('bottom')    # bottom align first tick
    yTick_objects[-1].label1.set_verticalalignment('top')  # top align last tick

    ax.xaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter('%0.1f'))
    ax.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter('%0.1f'))


if __name__ == '__main__':
    fig = plt.figure()
    ax = fig.add_subplot(111)
    stylize_plot(ax=ax, fig=fig)

    fig2 = plt.figure()
    ax2 = fig2.add_subplot(211)
    ax3 = fig2.add_subplot(212)
    stylize_plot(ax=ax2, fig=fig2)
    stylize_plot(ax=ax3, fig=fig2)

    fig3 = plt.figure()
    ax4 = fig3.add_subplot(121)
    ax5 = fig3.add_subplot(122)
    stylize_plot(ax=ax4, fig=fig3)
    stylize_plot(ax=ax5, fig=fig3)
    plt.show()

Figure 1 - 1 subplot Figure 2 - Vertical Subplots Figure 3 - Horizontal Subplots GUI Figure

hbb
  • 33
  • 10
  • What version of matplotlib are you using? All the figures are correct for me using matplotlib 2.2.3 – DavidG Jan 10 '19 at 10:38
  • Python version: 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] matplotlib version: 2.2.3 – hbb Jan 10 '19 at 11:18
  • Also, I typically work in Sublime Text (3) using the Anaconda IDE. Thinking maybe this had something to do with it I also ran it using IDLE and just from the command line and I got the same result (as shown in the original post) in all cases. – hbb Jan 10 '19 at 11:28
  • 1
    I noticed that your images have a very uncommon size (1536x767 pixels). Do you do anything else in your code that would let them appear in this format (and hence could also be responsible for the issue you see, that other people are unable to reproduce)? – ImportanceOfBeingErnest Jan 10 '19 at 11:51
  • 1
    The code used to produce the images is exactly what is provided above. The images posted are after maximizing the images to fit my screen. The original, un-maximized images appear normal. The problem is that in my GUI they always look incorrect (like in the post). I'll add a screenshot from the GUI to the post above. – hbb Jan 10 '19 at 12:18
  • For what it's worth, I posted this the other day (my first attempt to solve this issue). I realize it's a bit of a cumbersome post (which is why I think it didn't get much traction here), but it does have the code to basically re-create the GUI application of the problem in this current post. https://stackoverflow.com/questions/54077041/matplotlib-transforms-and-scaledtranslation-applications-for-tick-labels – hbb Jan 10 '19 at 12:34
  • I think we already discussed the option to add a callback on figure resizing in some related context? That's what you would need here. – ImportanceOfBeingErnest Jan 10 '19 at 15:37
  • I've got to admit that I'm pretty new to all this stuff, but I don't recall reading or discussing anything on figure resizing callbacks (not sure I even know exactly what the entails). If you have a link handy that would be very much appreciated. – hbb Jan 10 '19 at 15:39
  • I think I was refering to [this comment](https://stackoverflow.com/questions/53882211/matplotlib-tick-label-location-not-being-consistently-enforced#comment94614363_53882211). Instead (or in addition) to a `xlim_changed` event you would here need a `resize_event`. If this all sounds too complicated, you may start reading through [the event handling guide](https://matplotlib.org/users/event_handling.html) – ImportanceOfBeingErnest Jan 10 '19 at 15:42
  • Ah, ok. I didn't realize you were referring to this. I'll take a look at it, but in the mean time I'm still a bit uncertain that's the issue. In the screenshot from my GUI that I included above, nothing as been resized. This is how the plots appear when initialized. This is demonstrated in the link to my other post from a couple comments ago (https://stackoverflow.com/questions/54077041/matplotlib-transforms-and-scaledtranslation-applications-for-tick-labels). Since there is no "change" happening, why would I need a callback to any event? – hbb Jan 10 '19 at 17:35
  • Indeed, you would also need to connect to the draw event; that is because ticks will only be assingned at draw time. The resize event is then useful because your figure will be resized when being put into the GUI (it'll adjust to the space the GUI makes available for it, right?) – ImportanceOfBeingErnest Jan 21 '19 at 22:15

0 Answers0