Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Order Dependency In Setting Tick Locator and Formatter #21889

Open
ellabebop opened this issue Dec 9, 2021 · 0 comments
Open

Order Dependency In Setting Tick Locator and Formatter #21889

ellabebop opened this issue Dec 9, 2021 · 0 comments

Comments

@ellabebop
Copy link

ellabebop commented Dec 9, 2021

I'm seeing an inconsistency when I set the major tick locator and formatter in the "wrong" order, like clearing an axis does. I think it's happening because the tick locator is stored at least twice, and not all copies are being told when it changes.

The first copy is in the major ticker, axis.major.locator, and the second is in some types of tick formatters, like dates.AutoDateFormatter. Calling axis.set_major_locator() updates the copy in the ticker and the one in the current formatter, but calling axis.set_major_formatter() does not update the new formatter with the current locator. This allows the two to disagree if the locator is set before the formatter.

This example uses axis.clear() to illustrate the problem since that's what's tickling it for me. Internally, that method sets the locator and formatter to defaults, in the "wrong" order. This code should fail by assertion. Swapping the indicated lines causes it to succeed for the reasons given above.

import matplotlib.dates as mdates
import matplotlib.pyplot as plt

def main():
    fig = plt.figure()
    axes = fig.add_subplot(111)

    loc = mdates.AutoDateLocator(interval_multiples=True)
    fmt = mdates.AutoDateFormatter(loc)

    setTicks(axes, loc, fmt)
    axes.clear()                           # sets the locator, then the formatter
    setTicks(axes, loc, fmt)

def setTicks(axes, loc, fmt):
    axes.xaxis_date()
    axes.xaxis.set_major_locator(loc)      # swapping this line and...
    axes.xaxis.set_major_formatter(fmt)    # ...this line "fixes" the assertion failure

    locActual = axes.xaxis.get_major_locator()
    fmtActual = axes.xaxis.get_major_formatter()
    assert locActual is loc
    assert fmtActual is fmt
    assert fmtActual._locator is loc       # the assertion failure is here

if __name__ == "__main__":
    main()

I wouldn't expect the order those methods are called to matter. I'm on Red Hat Enterprise Linux 8.4, running Python 3.8.5 with matplotlib 3.3.2, but the current head commit looks unchanged in this area.

Not really knowing the code, my guess at a fix would be adding this at the bottom of axis._set_formatter().

    formatter._set_locator(level.locator)

I haven't tried this though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants