Skip to content

Conversation

leolchat
Copy link
Contributor

@leolchat leolchat commented Jul 20, 2020

PR Summary

Similar to #17971 but is able to write multiple levels when needed solving issues like #17958
It changes the user API though (format strings for zeros and offset are replaced by unit formatting and separator strings).

PR Checklist

  • Has Pytest style unit tests
  • Code is Flake 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/next_api_changes/* if API changed in a backward-incompatible way

@leolchat
Copy link
Contributor Author

import unittest

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

class MyTestCase(unittest.TestCase):
    def test_something(self):
        f = plt.figure()
        ax = plt.gca()

        dates = [np.datetime64( '2020-11-06 18:08:30'),  np.datetime64('2021-01-06 18:08:31')]
        zoom = None
        minticks = 5
        maxticks = 7
        offset = True

        # dates = [np.datetime64( '2020-11-06 18:08:30'),  np.datetime64('2021-01-06 18:08:31')]
        # zoom = np.datetime64( '2020-06-06 18:00:00.3'), np.datetime64( '2020-06-06 18:00:00.5')
        # minticks = 5
        # maxticks = 7
        # offset = True

        # dates = [np.datetime64( '2020-11-06 18:08:30'),  np.datetime64('2021-01-06 18:08:31')]
        # zoom = np.datetime64( '2020-06-06 18:08:01.3'), np.datetime64( '2020-06-06 18:08:01.5')
        # minticks = 5
        # maxticks = 7
        # offset = True

        # dates = [np.datetime64( '2020-06-06 18:08:30'),  np.datetime64('2021-01-06 18:08:31')]
        # zoom = None
        # minticks = 2
        # maxticks = 4
        # offset = True

        # dates = [np.datetime64( '2020-06-06 18:08:30'),  np.datetime64('2021-01-06 18:08:31')]
        # zoom = None
        # minticks = 10
        # maxticks = 20
        # offset = True

        ax.plot(dates, [0, 1])
        ax.set_xticks(dates)

        locator = mdates.AutoDateLocator(minticks=minticks, maxticks=maxticks)
        formatter = mdates.ConciseDateFormatter(locator, show_offset=offset)
        ax.xaxis.set_major_locator(locator)
        ax.xaxis.set_major_formatter(formatter)
        # f.autofmt_xdate()

        if zoom:
            ax.set_xlim(*zoom)
        plt.grid()
        plt.show()

if __name__ == '__main__':
    unittest.main()

Gives:
image

@leolchat
Copy link
Contributor Author

leolchat commented Jul 20, 2020

Example in #17958 gives (I used autofmt_xdate to not have overlap)
image

It corresponds to

        dates = [np.datetime64('2020-06-06 18:08:30'), np.datetime64('2021-06-06 18:08:31')]
        zoom = (np.datetime64('2020-06-06 18:08:30.3'), np.datetime64('2021-06-06 18:08:30.5'))
        minticks = 20
        maxticks = 30
        offset = True

@leolchat
Copy link
Contributor Author

leolchat commented Jul 20, 2020

Zooming in to have only one year shows the offset:

        dates = [np.datetime64('2020-06-06 18:08:30'), np.datetime64('2021-06-06 18:08:31')]
        zoom = (np.datetime64('2020-06-06 18:08:30.3'), np.datetime64('2020-12-06 18:08:30.5'))
        minticks = 20
        maxticks = 30
        offset = True

image

Note how the first tick is labelled with the month even if the day is also non zero, ensuring no ambiguity.

@leolchat
Copy link
Contributor Author

leolchat commented Jul 20, 2020

Zooming in some more show the small struggle with good defaults to resolve hour:minute vs minute:second ambiguity (and my current attempt, using hourhminute:second)

        dates = [np.datetime64('2020-06-06 18:08:30'), np.datetime64('2021-06-06 18:08:31')]
        zoom = (np.datetime64('2020-06-06 18:08:30.3'), np.datetime64('2020-06-10 18:08:30.5'))
        minticks = 20
        maxticks = 30
        offset = True

image

@leolchat
Copy link
Contributor Author

zooming even more

        dates = [np.datetime64('2020-06-06 18:08:30'), np.datetime64('2021-06-06 18:08:31')]
        zoom = (np.datetime64('2020-06-06 22:08:30.3'), np.datetime64('2020-06-07 01:08:30.5'))
        minticks = 20
        maxticks = 30
        offset = True

image

@leolchat
Copy link
Contributor Author

zooming in more and handling the edge corner when first tick and offset share a zero at level

        dates = [np.datetime64('2020-06-06 18:08:30'), np.datetime64('2021-06-06 18:08:31')]
        zoom = (np.datetime64('2020-06-07 00:08:30.3'), np.datetime64('2020-06-07 01:08:30.5'))
        minticks = 20
        maxticks = 30
        offset = True

image

@leolchat
Copy link
Contributor Author

Old level code removing trailing zeroes is now broken (it was already kind of hackish).
Zooming in more shows current approach not removing zeroes, but handling sub second correctly (fixing #17269 too):

        dates = [np.datetime64( '2020-11-06 18:08:30'),  np.datetime64('2021-01-06 18:08:31')]
        zoom = np.datetime64( '2020-06-06 18:08:01.3'), np.datetime64( '2020-06-06 18:08:01.5')
        minticks = 5
        maxticks = 7
        offset = True

image

@leolchat
Copy link
Contributor Author

@jklymak any feedback?

@jklymak
Copy link
Member

jklymak commented Jul 20, 2020

I think at this point, this is a new Formatter, which is great.

I think it'd be nice if we had an easy way for folks to plug their own formatters in as default w/o the 4-line song and dance. However, if you write your own little (one-file) package, you can register the formatter at import time.

@leolchat leolchat marked this pull request as draft July 21, 2020 00:37
@dstansby dstansby requested a review from jklymak September 20, 2020 16:25
@jklymak jklymak removed their request for review September 21, 2020 14:45
@jklymak
Copy link
Member

jklymak commented Feb 16, 2021

I'm going to close this - it is simply a different formatter than ConciseDateFormatter, and its advantages are not clear. In general I strongly prefer what is done in ConciseDateFormatter, so unless there is a groundswell to replace it, I think this alternative should be its own package.

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

Successfully merging this pull request may close these issues.

3 participants