From 8b3df04ebab33e524530bc31ee6a6308506a09d5 Mon Sep 17 00:00:00 2001 From: MKhadra Date: Tue, 10 Mar 2020 23:37:44 -0400 Subject: [PATCH 1/7] Added two new parameters: xtick.minor.ndivs and ytick.minor.ndivs and a corresponding validate function --- lib/matplotlib/rcsetup.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index 9eefcccdcbc7..dcfa47df859e 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -791,6 +791,20 @@ def validate_hatch(s): validate_hatchlist = _listify_validator(validate_hatch) validate_dashlist = _listify_validator(validate_nseq_float(allow_none=True)) +def validate_minor_tick_ndivs(n): + """ + Validate the given ndiv parameter for minor ticks. + ndiv can be either the string 'auto' or a non-negative integer. + """ + if isinstance(n, int): + if (0 <= n): + return n + else: + raise RuntimeError(f'Value must be >=0; got {n}') + elif (n == 'auto'): + return n + else: + raise ValueError("Value must be a non-negative int or 'auto'") _prop_validators = { 'color': _listify_validator(validate_color_for_prop_cycle, @@ -1337,6 +1351,7 @@ def _convert_validator_spec(key, conv): 'xtick.minor.bottom': [True, validate_bool], # draw x axis bottom minor ticks 'xtick.major.top': [True, validate_bool], # draw x axis top major ticks 'xtick.major.bottom': [True, validate_bool], # draw x axis bottom major ticks + 'xtick.minor.ndivs': ['auto', validate_minor_tick_ndivs], # default number of minor ticks to display between each pair of major ticks # fontsize of the xtick labels 'xtick.labelsize': ['medium', validate_fontsize], @@ -1360,6 +1375,7 @@ def _convert_validator_spec(key, conv): 'ytick.minor.right': [True, validate_bool], # draw y axis right minor ticks 'ytick.major.left': [True, validate_bool], # draw y axis left major ticks 'ytick.major.right': [True, validate_bool], # draw y axis right major ticks + 'ytick.minor.ndivs': ['auto', validate_minor_tick_ndivs], # default number of minor ticks to display between each pair of major ticks # fontsize of the ytick labels 'ytick.labelsize': ['medium', validate_fontsize], From 72207e8caa1a62e9a939b2de6188e2df7ae60962 Mon Sep 17 00:00:00 2001 From: MKhadra Date: Tue, 10 Mar 2020 23:41:18 -0400 Subject: [PATCH 2/7] Added new keys to reflect two new parameters from previous commit --- matplotlibrc.template | 2 ++ 1 file changed, 2 insertions(+) diff --git a/matplotlibrc.template b/matplotlibrc.template index 2dbe7bbb9b29..0072d875bcb6 100644 --- a/matplotlibrc.template +++ b/matplotlibrc.template @@ -460,6 +460,7 @@ #xtick.minor.top: True # draw x axis top minor ticks #xtick.minor.bottom: True # draw x axis bottom minor ticks #xtick.alignment: center # alignment of xticks +#xtick.minor.ndivs: auto # default number of minor ticks to display between each pair of major ticks #ytick.left: True # draw ticks on the left side #ytick.right: False # draw ticks on the right side @@ -480,6 +481,7 @@ #ytick.minor.left: True # draw y axis left minor ticks #ytick.minor.right: True # draw y axis right minor ticks #ytick.alignment: center_baseline # alignment of yticks +#ytick.minor.ndivs: auto # default number of minor ticks to display between each pair of major ticks ## *************************************************************************** From 132a5075d403c91a2073db2871fe5cde91e090dd Mon Sep 17 00:00:00 2001 From: MKhadra Date: Tue, 10 Mar 2020 23:59:14 -0400 Subject: [PATCH 3/7] Added new cases in __call__ method of AutoMinorLocator class to implement new functionality --- lib/matplotlib/ticker.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py index e3f9c681d8c7..d0e2e194f9b1 100644 --- a/lib/matplotlib/ticker.py +++ b/lib/matplotlib/ticker.py @@ -2757,7 +2757,8 @@ def __init__(self, n=None): major ticks; e.g., n=2 will place a single minor tick midway between major ticks. - If *n* is omitted or None, it will be set to 5 or 4. + If *n* is omitted or None, the value stored in rcParams will be used. + If *n* is 'auto', it will be set to 5 or 4. """ self.ndivs = n @@ -2779,6 +2780,12 @@ def __call__(self): return [] if self.ndivs is None: + if Locator.axis.__name__ == 'xaxis': + self.ndivs = rcParams['xtick.minor.ndivs'] + else: + self.ndivs = rcParams['ytick.minor.ndivs'] + + if self.ndivs == 'auto': majorstep_no_exponent = 10 ** (np.log10(majorstep) % 1) From bc98435097cb287f4502d8181037ea95a6f556d7 Mon Sep 17 00:00:00 2001 From: MKhadra Date: Wed, 11 Mar 2020 10:32:53 -0400 Subject: [PATCH 4/7] Made code flake8 compliant --- lib/matplotlib/rcsetup.py | 5 +++-- lib/matplotlib/ticker.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index dcfa47df859e..e9edde860ef2 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -791,6 +791,7 @@ def validate_hatch(s): validate_hatchlist = _listify_validator(validate_hatch) validate_dashlist = _listify_validator(validate_nseq_float(allow_none=True)) + def validate_minor_tick_ndivs(n): """ Validate the given ndiv parameter for minor ticks. @@ -1351,7 +1352,7 @@ def _convert_validator_spec(key, conv): 'xtick.minor.bottom': [True, validate_bool], # draw x axis bottom minor ticks 'xtick.major.top': [True, validate_bool], # draw x axis top major ticks 'xtick.major.bottom': [True, validate_bool], # draw x axis bottom major ticks - 'xtick.minor.ndivs': ['auto', validate_minor_tick_ndivs], # default number of minor ticks to display between each pair of major ticks + 'xtick.minor.ndivs': ['auto', validate_minor_tick_ndivs], # default number of minor ticks to display between each pair of major ticks # fontsize of the xtick labels 'xtick.labelsize': ['medium', validate_fontsize], @@ -1375,7 +1376,7 @@ def _convert_validator_spec(key, conv): 'ytick.minor.right': [True, validate_bool], # draw y axis right minor ticks 'ytick.major.left': [True, validate_bool], # draw y axis left major ticks 'ytick.major.right': [True, validate_bool], # draw y axis right major ticks - 'ytick.minor.ndivs': ['auto', validate_minor_tick_ndivs], # default number of minor ticks to display between each pair of major ticks + 'ytick.minor.ndivs': ['auto', validate_minor_tick_ndivs], # default number of minor ticks to display between each pair of major ticks # fontsize of the ytick labels 'ytick.labelsize': ['medium', validate_fontsize], diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py index d0e2e194f9b1..cb89f5a36229 100644 --- a/lib/matplotlib/ticker.py +++ b/lib/matplotlib/ticker.py @@ -2781,9 +2781,9 @@ def __call__(self): if self.ndivs is None: if Locator.axis.__name__ == 'xaxis': - self.ndivs = rcParams['xtick.minor.ndivs'] + self.ndivs = mpl.rcParams['xtick.minor.ndivs'] else: - self.ndivs = rcParams['ytick.minor.ndivs'] + self.ndivs = mpl.rcParams['ytick.minor.ndivs'] if self.ndivs == 'auto': From 2e0e6f4d5eb37981db0e5fd4a95d3f949f3686ff Mon Sep 17 00:00:00 2001 From: MKhadra Date: Wed, 11 Mar 2020 10:52:34 -0400 Subject: [PATCH 5/7] Fixed error in ticker.py --- lib/matplotlib/ticker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py index cb89f5a36229..066d1432a49f 100644 --- a/lib/matplotlib/ticker.py +++ b/lib/matplotlib/ticker.py @@ -2780,7 +2780,7 @@ def __call__(self): return [] if self.ndivs is None: - if Locator.axis.__name__ == 'xaxis': + if self.axis.__name__ == 'xaxis': self.ndivs = mpl.rcParams['xtick.minor.ndivs'] else: self.ndivs = mpl.rcParams['ytick.minor.ndivs'] From 54583093a520b04b16d1acd3e67412ed92af920b Mon Sep 17 00:00:00 2001 From: MKhadra Date: Wed, 11 Mar 2020 13:03:52 -0400 Subject: [PATCH 6/7] Unit tests added to test_ticker.py --- lib/matplotlib/tests/test_ticker.py | 64 +++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/lib/matplotlib/tests/test_ticker.py b/lib/matplotlib/tests/test_ticker.py index 1495a1877e65..784b9826abd9 100644 --- a/lib/matplotlib/tests/test_ticker.py +++ b/lib/matplotlib/tests/test_ticker.py @@ -194,6 +194,70 @@ def test_additional(self, lim, ref): assert_almost_equal(ax.yaxis.get_ticklocs(minor=True), ref) + def test_ndivs_rcParams_auto(self): + # when no parameter is given rcParams should be used + # auto + mpl.rc_context(rc={'xtick.minor.ndivs': 'auto'}) + mpl.rc_context(rc={'ytick.minor.ndivs': 'auto'}) + fig, ax = plt.subplots() + ax.set_xlim(0, 1.39) + ax.set_ylim(0, 1.39) + ax.xaxis.set_minor_locator(mticker.AutoMinorLocator()) + ax.yaxis.set_minor_locator(mticker.AutoMinorLocator()) + + test_value = np.array([0.05, 0.1, 0.15, 0.25, 0.3, 0.35, 0.45, + 0.5, 0.55, 0.65, 0.7, 0.75, 0.85, 0.9, + 0.95, 1.05, 1.1, 1.15, 1.25, 1.3, 1.35]) + assert_almost_equal(ax.xaxis.get_ticklocs(minor=True), test_value) + assert_almost_equal(ax.yaxis.get_ticklocs(minor=True), test_value) + + def test_ndivs_rcParams_int(self): + # when no parameter is given rcParams should be used + # non-neg int + mpl.rc_context(rc={'xtick.minor.ndivs': 2}) + mpl.rc_context(rc={'ytick.minor.ndivs': 2}) + fig, ax = plt.subplots() + ax.set_xlim(0, 4) + ax.xaxis.set_major_locator(mticker.MultipleLocator(1)) + ax.xaxis.set_minor_locator(mticker.AutoMinorLocator()) + + ax.set_ylim(0, 4) + ax.yaxis.set_major_locator(mticker.MultipleLocator(1)) + ax.yaxis.set_minor_locator(mticker.AutoMinorLocator()) + + test_value = np.array([0.5, 1.5, 2.5, 3.5]) + assert_almost_equal(ax.xaxis.get_ticklocs(minor=True), test_value) + assert_almost_equal(ax.yaxis.get_ticklocs(minor=True), test_value) + + def test_ndivs_auto(self): + # when auto is given set ndivs to either 4 or 5 + fig, ax = plt.subplots() + ax.set_xlim(0, 1.39) + ax.set_ylim(0, 1.39) + ax.xaxis.set_minor_locator(mticker.AutoMinorLocator('auto')) + ax.yaxis.set_minor_locator(mticker.AutoMinorLocator('auto')) + + test_value = np.array([0.05, 0.1, 0.15, 0.25, 0.3, 0.35, 0.45, + 0.5, 0.55, 0.65, 0.7, 0.75, 0.85, 0.9, + 0.95, 1.05, 1.1, 1.15, 1.25, 1.3, 1.35]) + assert_almost_equal(ax.xaxis.get_ticklocs(minor=True), test_value) + assert_almost_equal(ax.yaxis.get_ticklocs(minor=True), test_value) + + def test_ndivs_int(self): + # when an integer is given, use that integer + fig, ax = plt.subplots() + ax.set_xlim(0, 4) + ax.xaxis.set_major_locator(mticker.MultipleLocator(1)) + ax.xaxis.set_minor_locator(mticker.AutoMinorLocator(2)) + + ax.set_ylim(0, 4) + ax.yaxis.set_major_locator(mticker.MultipleLocator(1)) + ax.yaxis.set_minor_locator(mticker.AutoMinorLocator(2)) + + test_value = np.array([0.5, 1.5, 2.5, 3.5]) + assert_almost_equal(ax.xaxis.get_ticklocs(minor=True), test_value) + assert_almost_equal(ax.yaxis.get_ticklocs(minor=True), test_value) + class TestLogLocator: def test_basic(self): From dad689e51da56af16e875d3806fa0e6b40917140 Mon Sep 17 00:00:00 2001 From: MKhadra Date: Tue, 1 Sep 2020 17:57:41 -0400 Subject: [PATCH 7/7] flake8 compliant --- lib/matplotlib/rcsetup.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index c17800c095d8..3a188feaad38 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -1302,7 +1302,8 @@ def _convert_validator_spec(key, conv): "xtick.minor.bottom": validate_bool, # draw bottom minor xticks "xtick.major.top": validate_bool, # draw top major xticks "xtick.major.bottom": validate_bool, # draw bottom major xticks - "xtick.minor.ndivs": ['auto', validate_minor_tick_ndivs], # default number of minor ticks to display between each pair of major ticks + "xtick.minor.ndivs": ['auto', validate_minor_tick_ndivs], + # default number of minor ticks to display between each pair of major ticks "xtick.labelsize": validate_fontsize, # fontsize of xtick labels "xtick.direction": validate_string, # direction of xticks "xtick.alignment": ["center", "right", "left"], @@ -1326,7 +1327,8 @@ def _convert_validator_spec(key, conv): "ytick.major.left": validate_bool, # draw left major yticks "ytick.major.right": validate_bool, # draw right major yticks "ytick.labelsize": validate_fontsize, # fontsize of ytick labels - "ytick.minor.ndivs": ['auto', validate_minor_tick_ndivs], # default number of minor ticks to display between each pair of major ticks + "ytick.minor.ndivs": ['auto', validate_minor_tick_ndivs], + # default number of minor ticks to display between each pair of major ticks "ytick.direction": validate_string, # direction of yticks "ytick.alignment": [ "center", "top", "bottom", "baseline", "center_baseline"],