| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,31 @@ | |||
| 1 | + New rcParams for dates: set converter and whether to use interval_multiples | ||
| 2 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 3 | + | ||
| 4 | + The new :rc:`date.converter` allows toggling between | ||
| 5 | + `matplotlib.dates.DateConverter` and `matplotlib.dates.ConciseDateConverter` | ||
| 6 | + using the strings 'auto' and 'concise' respectively. | ||
| 7 | + | ||
| 8 | + The new :rc:`date.interval_multiples` allows toggling between the dates | ||
| 9 | + locator trying to pick ticks at set intervals (i.e. day 1 and 15 of the | ||
| 10 | + month), versus evenly spaced ticks that start where ever the | ||
| 11 | + timeseries starts: | ||
| 12 | + | ||
| 13 | + .. plot:: | ||
| 14 | + :include-source: True | ||
| 15 | + | ||
| 16 | + import matplotlib.pyplot as plt | ||
| 17 | + import numpy as np | ||
| 18 | + | ||
| 19 | + dates = np.arange('2001-01-10', '2001-05-23', dtype='datetime64[D]') | ||
| 20 | + y = np.sin(dates.astype(float) / 10) | ||
| 21 | + fig, axs = plt.subplots(nrows=2, constrained_layout=True) | ||
| 22 | + | ||
| 23 | + plt.rcParams['date.converter'] = 'concise' | ||
| 24 | + plt.rcParams['date.interval_multiples'] = True | ||
| 25 | + ax = axs[0] | ||
| 26 | + ax.plot(dates, y) | ||
| 27 | + | ||
| 28 | + plt.rcParams['date.converter'] = 'auto' | ||
| 29 | + plt.rcParams['date.interval_multiples'] = False | ||
| 30 | + ax = axs[1] | ||
| 31 | + ax.plot(dates, y) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1834,8 +1834,11 @@ class DateConverter(units.ConversionInterface): | |||
| 1834 | 1834 | The 'unit' tag for such data is None or a tzinfo instance. | |
| 1835 | 1835 | """ | |
| 1836 | 1836 | ||
| 1837 | - @staticmethod | ||
| 1838 | - def axisinfo(unit, axis): | ||
| 1837 | + def __init__(self, *, interval_multiples=True): | ||
| 1838 | + self._interval_multiples = interval_multiples | ||
| 1839 | + super().__init__() | ||
| 1840 | + | ||
| 1841 | + def axisinfo(self, unit, axis): | ||
| 1839 | 1842 | """ | |
| 1840 | 1843 | Return the `~matplotlib.units.AxisInfo` for *unit*. | |
| 1841 | 1844 | ||
@@ -1844,7 +1847,8 @@ def axisinfo(unit, axis): | |||
| 1844 | 1847 | """ | |
| 1845 | 1848 | tz = unit | |
| 1846 | 1849 | ||
| 1847 | - majloc = AutoDateLocator(tz=tz) | ||
| 1850 | + majloc = AutoDateLocator(tz=tz, | ||
| 1851 | + interval_multiples=self._interval_multiples) | ||
| 1848 | 1852 | majfmt = AutoDateFormatter(majloc, tz=tz) | |
| 1849 | 1853 | datemin = datetime.date(2000, 1, 1) | |
| 1850 | 1854 | datemax = datetime.date(2010, 1, 1) | |
@@ -1886,17 +1890,19 @@ class ConciseDateConverter(DateConverter): | |||
| 1886 | 1890 | # docstring inherited | |
| 1887 | 1891 | ||
| 1888 | 1892 | def __init__(self, formats=None, zero_formats=None, offset_formats=None, | |
| 1889 | - show_offset=True): | ||
| 1893 | + show_offset=True, *, interval_multiples=True): | ||
| 1890 | 1894 | self._formats = formats | |
| 1891 | 1895 | self._zero_formats = zero_formats | |
| 1892 | 1896 | self._offset_formats = offset_formats | |
| 1893 | 1897 | self._show_offset = show_offset | |
| 1898 | + self._interval_multiples = interval_multiples | ||
| 1894 | 1899 | super().__init__() | |
| 1895 | 1900 | ||
| 1896 | 1901 | def axisinfo(self, unit, axis): | |
| 1897 | 1902 | # docstring inherited | |
| 1898 | 1903 | tz = unit | |
| 1899 | - majloc = AutoDateLocator(tz=tz) | ||
| 1904 | + majloc = AutoDateLocator(tz=tz, | ||
| 1905 | + interval_multiples=self._interval_multiples) | ||
| 1900 | 1906 | majfmt = ConciseDateFormatter(majloc, tz=tz, formats=self._formats, | |
| 1901 | 1907 | zero_formats=self._zero_formats, | |
| 1902 | 1908 | offset_formats=self._offset_formats, | |
@@ -1907,6 +1913,42 @@ def axisinfo(self, unit, axis): | |||
| 1907 | 1913 | default_limits=(datemin, datemax)) | |
| 1908 | 1914 | ||
| 1909 | 1915 | ||
| 1910 | - units.registry[np.datetime64] = DateConverter() | ||
| 1911 | - units.registry[datetime.date] = DateConverter() | ||
| 1912 | - units.registry[datetime.datetime] = DateConverter() | ||
| 1916 | + class _rcParam_helper: | ||
| 1917 | + """ | ||
| 1918 | + This helper class is so that we can set the converter for dates | ||
| 1919 | + via the validator for the rcParams `date.converter` and | ||
| 1920 | + `date.interval_multiples`. Never instatiated. | ||
| 1921 | + """ | ||
| 1922 | + | ||
| 1923 | + conv_st = 'auto' | ||
| 1924 | + int_mult = True | ||
| 1925 | + | ||
| 1926 | + @classmethod | ||
| 1927 | + def set_converter(cls, s): | ||
| 1928 | + """Called by validator for rcParams date.converter""" | ||
| 1929 | + cls.conv_st = s | ||
| 1930 | + cls.register_converters() | ||
| 1931 | + | ||
| 1932 | + @classmethod | ||
| 1933 | + def set_int_mult(cls, b): | ||
| 1934 | + """Called by validator for rcParams date.interval_multiples""" | ||
| 1935 | + cls.int_mult = b | ||
| 1936 | + cls.register_converters() | ||
| 1937 | + | ||
| 1938 | + @classmethod | ||
| 1939 | + def register_converters(cls): | ||
| 1940 | + """ | ||
| 1941 | + Helper to register the date converters when rcParams `date.converter` | ||
| 1942 | + and `date.interval_multiples` are changed. Called by the helpers | ||
| 1943 | + above. | ||
| 1944 | + """ | ||
| 1945 | + if cls.conv_st == 'concise': | ||
| 1946 | + converter = ConciseDateConverter | ||
| 1947 | + else: | ||
| 1948 | + converter = DateConverter | ||
| 1949 | + | ||
| 1950 | + interval_multiples = cls.int_mult | ||
| 1951 | + convert = converter(interval_multiples=interval_multiples) | ||
| 1952 | + units.registry[np.datetime64] = convert | ||
| 1953 | + units.registry[datetime.date] = convert | ||
| 1954 | + units.registry[datetime.datetime] = convert | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -20,6 +20,7 @@ | |||
| 20 | 20 | import operator | |
| 21 | 21 | import os | |
| 22 | 22 | import re | |
| 23 | + import sys | ||
| 23 | 24 | ||
| 24 | 25 | import numpy as np | |
| 25 | 26 | ||
@@ -174,6 +175,23 @@ def validate_bool_maybe_none(b): | |||
| 174 | 175 | raise ValueError('Could not convert "%s" to bool' % b) | |
| 175 | 176 | ||
| 176 | 177 | ||
| 178 | + def _validate_date_converter(s): | ||
| 179 | + s = validate_string(s) | ||
| 180 | + mdates = sys.modules.get("matplotlib.dates") | ||
| 181 | + if mdates: | ||
| 182 | + mdates._rcParam_helper.set_converter(s) | ||
| 183 | + | ||
| 184 | + | ||
| 185 | + def _validate_date_int_mult(s): | ||
| 186 | + if s is None: | ||
| 187 | + return | ||
| 188 | + s = validate_bool(s) | ||
| 189 | + # only do this if dates is already imported... | ||
| 190 | + mdates = sys.modules.get("matplotlib.dates") | ||
| 191 | + if mdates: | ||
| 192 | + mdates._rcParam_helper.set_int_mult(s) | ||
| 193 | + | ||
| 194 | + | ||
| 177 | 195 | def _validate_tex_preamble(s): | |
| 178 | 196 | if s is None or s == 'None': | |
| 179 | 197 | cbook.warn_deprecated( | |
@@ -1271,13 +1289,19 @@ def _convert_validator_spec(key, conv): | |||
| 1271 | 1289 | "date.autoformatter.second": validate_string, | |
| 1272 | 1290 | "date.autoformatter.microsecond": validate_string, | |
| 1273 | 1291 | ||
| 1292 | + # 'auto', 'concise', 'auto-noninterval' | ||
| 1293 | + 'date.converter': _validate_date_converter, | ||
| 1294 | + # for auto date locator, choose interval_multiples | ||
| 1295 | + 'date.interval_multiples': _validate_date_int_mult, | ||
| 1296 | + | ||
| 1274 | 1297 | # legend properties | |
| 1275 | 1298 | "legend.fancybox": validate_bool, | |
| 1276 | 1299 | "legend.loc": _ignorecase([ | |
| 1277 | 1300 | "best", | |
| 1278 | 1301 | "upper right", "upper left", "lower left", "lower right", "right", | |
| 1279 | 1302 | "center left", "center right", "lower center", "upper center", | |
| 1280 | 1303 | "center"]), | |
| 1304 | + | ||
| 1281 | 1305 | # the number of points in the legend line | |
| 1282 | 1306 | "legend.numpoints": validate_int, | |
| 1283 | 1307 | # the number of points in the legend line for scatter | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -958,3 +958,43 @@ def test_warn_notintervals(): | |||
| 958 | 958 | mdates.date2num(dates[-1])) | |
| 959 | 959 | with pytest.warns(UserWarning, match="AutoDateLocator was unable") as rec: | |
| 960 | 960 | locs = locator() | |
| 961 | + | ||
| 962 | + | ||
| 963 | + def test_change_converter(): | ||
| 964 | + | ||
| 965 | + plt.rcParams['date.converter'] = 'concise' | ||
| 966 | + dates = np.arange('2020-01-01', '2020-05-01', dtype='datetime64[D]') | ||
| 967 | + fig, ax = plt.subplots() | ||
| 968 | + | ||
| 969 | + ax.plot(dates, np.arange(len(dates))) | ||
| 970 | + fig.canvas.draw() | ||
| 971 | + assert ax.get_xticklabels()[0].get_text() == 'Jan' | ||
| 972 | + assert ax.get_xticklabels()[1].get_text() == '15' | ||
| 973 | + | ||
| 974 | + plt.rcParams['date.converter'] = 'auto' | ||
| 975 | + fig, ax = plt.subplots() | ||
| 976 | + | ||
| 977 | + ax.plot(dates, np.arange(len(dates))) | ||
| 978 | + fig.canvas.draw() | ||
| 979 | + assert ax.get_xticklabels()[0].get_text() == 'Jan 01 2020' | ||
| 980 | + assert ax.get_xticklabels()[1].get_text() == 'Jan 15 2020' | ||
| 981 | + | ||
| 982 | + | ||
| 983 | + def test_change_interval_multiples(): | ||
| 984 | + | ||
| 985 | + plt.rcParams['date.interval_multiples'] = False | ||
| 986 | + dates = np.arange('2020-01-10', '2020-05-01', dtype='datetime64[D]') | ||
| 987 | + fig, ax = plt.subplots() | ||
| 988 | + | ||
| 989 | + ax.plot(dates, np.arange(len(dates))) | ||
| 990 | + fig.canvas.draw() | ||
| 991 | + assert ax.get_xticklabels()[0].get_text() == 'Jan 10 2020' | ||
| 992 | + assert ax.get_xticklabels()[1].get_text() == 'Jan 24 2020' | ||
| 993 | + | ||
| 994 | + plt.rcParams['date.interval_multiples'] = 'True' | ||
| 995 | + fig, ax = plt.subplots() | ||
| 996 | + | ||
| 997 | + ax.plot(dates, np.arange(len(dates))) | ||
| 998 | + fig.canvas.draw() | ||
| 999 | + assert ax.get_xticklabels()[0].get_text() == 'Jan 15 2020' | ||
| 1000 | + assert ax.get_xticklabels()[1].get_text() == 'Feb 01 2020' | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -442,10 +442,13 @@ | |||
| 442 | 442 | #date.autoformatter.minute: %d %H:%M | |
| 443 | 443 | #date.autoformatter.second: %H:%M:%S | |
| 444 | 444 | #date.autoformatter.microsecond: %M:%S.%f | |
| 445 | - | ||
| 446 | 445 | ## The reference date for Matplotlib's internal date representation | |
| 447 | 446 | ## See https://matplotlib.org/examples/ticks_and_spines/date_precision_and_epochs.py | |
| 448 | 447 | #date.epoch: 1970-01-01T00:00:00 | |
| 448 | + ## 'auto', 'concise': | ||
| 449 | + #date.converter: auto | ||
| 450 | + ## For auto converter whether to use interval_multiples: | ||
| 451 | + #date.interval_multiples: True | ||
| 449 | 452 | ||
| 450 | 453 | ## *************************************************************************** | |
| 451 | 454 | ## * TICKS * | |
| Back | FazBrowse Home | New Git URL |
0 commit comments