diff --git a/doc/api/api_changes/2017-07-03-DS-logscale_masked.rst b/doc/api/api_changes/2017-07-03-DS-logscale_masked.rst new file mode 100644 index 000000000000..5de845f90a7c --- /dev/null +++ b/doc/api/api_changes/2017-07-03-DS-logscale_masked.rst @@ -0,0 +1,8 @@ +Default behavior of log scales changed to mask <= 0 values +`````````````````````````````````````````````````````````` + +Calling `matplotlib.axes.Axes.set_xscale` or `matplotlib.axes.Axes.set_yscale` +now uses 'mask' as the default method to handle invalid values (as opposed to +'clip'). This means that any values <= 0 on a log scale will not be shown. + +Previously they were clipped to a very small number and shown. diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index bfbf81bc67be..85877358e754 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -1578,7 +1578,6 @@ def semilogx(self, *args, **kwargs): self.cla() d = {'basex': kwargs.pop('basex', 10), 'subsx': kwargs.pop('subsx', None), - 'nonposx': kwargs.pop('nonposx', 'mask'), } self.set_xscale('log', **d) @@ -1629,7 +1628,6 @@ def semilogy(self, *args, **kwargs): self.cla() d = {'basey': kwargs.pop('basey', 10), 'subsy': kwargs.pop('subsy', None), - 'nonposy': kwargs.pop('nonposy', 'mask'), } self.set_yscale('log', **d) b = self._hold @@ -2753,6 +2751,10 @@ def errorbar(self, x, y, yerr=None, xerr=None, %(Line2D)s + Notes + ----- + Error bars with negative values will not be shown when plotted on a + logarithmic axis. """ kwargs = cbook.normalize_kwargs(kwargs, _alias_map) # anything that comes in as 'None', drop so the default thing diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 3dab3749ebf0..e5f189c94b62 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -2961,10 +2961,10 @@ def set_xscale(self, value, **kwargs): matplotlib.scale.LogisticTransform : logit transform """ - # If the scale is being set to log, clip nonposx to prevent headaches + # If the scale is being set to log, mask nonposx to prevent headaches # around zero if value.lower() == 'log' and 'nonposx' not in kwargs: - kwargs['nonposx'] = 'clip' + kwargs['nonposx'] = 'mask' g = self.get_shared_x_axes() for ax in g.get_siblings(self): @@ -3255,10 +3255,10 @@ def set_yscale(self, value, **kwargs): matplotlib.scale.LogisticTransform : logit transform """ - # If the scale is being set to log, clip nonposy to prevent headaches + # If the scale is being set to log, mask nonposy to prevent headaches # around zero if value.lower() == 'log' and 'nonposy' not in kwargs: - kwargs['nonposy'] = 'clip' + kwargs['nonposy'] = 'mask' g = self.get_shared_y_axes() for ax in g.get_siblings(self): diff --git a/lib/matplotlib/tests/baseline_images/test_axes/log_scales.png b/lib/matplotlib/tests/baseline_images/test_axes/log_scales.png index 876b47caedb6..9e68e62fd75d 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/log_scales.png and b/lib/matplotlib/tests/baseline_images/test_axes/log_scales.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/log_scales.svg b/lib/matplotlib/tests/baseline_images/test_axes/log_scales.svg index 2e63e7be1870..596ba00f9b67 100644 --- a/lib/matplotlib/tests/baseline_images/test_axes/log_scales.svg +++ b/lib/matplotlib/tests/baseline_images/test_axes/log_scales.svg @@ -27,8 +27,7 @@ z " style="fill:#ffffff;"/> - +" id="m368fc901b1" style="stroke:#000000;stroke-width:0.5;"/> - + +" id="mc63e59a608" style="stroke:#000000;stroke-width:0.5;"/> - + @@ -142,6 +141,7 @@ Q 56.59375 19.140625 48.40625 8.859375 Q 40.234375 -1.421875 26.421875 -1.421875 Q 22.703125 -1.421875 18.890625 -0.6875 Q 15.09375 0.046875 10.984375 1.515625 +z M 30.609375 32.421875 Q 37.25 32.421875 41.125 36.953125 Q 45.015625 41.5 45.015625 49.421875 @@ -151,6 +151,7 @@ Q 23.96875 66.40625 20.09375 61.84375 Q 16.21875 57.28125 16.21875 49.421875 Q 16.21875 41.5 20.09375 36.953125 Q 23.96875 32.421875 30.609375 32.421875 +z " id="DejaVuSans-39"/> @@ -181,12 +184,12 @@ Q 19.53125 74.21875 31.78125 74.21875 - + - + @@ -215,12 +218,12 @@ z - + - + @@ -248,6 +251,7 @@ Q 53.21875 48.921875 51.53125 44.890625 Q 49.859375 40.875 45.40625 35.40625 Q 44.1875 33.984375 37.640625 27.21875 Q 31.109375 20.453125 19.1875 8.296875 +z " id="DejaVuSans-32"/> @@ -261,176 +265,176 @@ Q 31.109375 20.453125 19.1875 8.296875 +" id="mce6b333cae" style="stroke:#000000;stroke-width:0.5;"/> - + +" id="m8d518e7239" style="stroke:#000000;stroke-width:0.5;"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -441,20 +445,20 @@ L 0 2 +" id="m556f96d829" style="stroke:#000000;stroke-width:0.5;"/> - + +" id="m27e32ca04a" style="stroke:#000000;stroke-width:0.5;"/> - + @@ -509,12 +513,12 @@ z - + - + @@ -530,12 +534,12 @@ z - + - + @@ -553,104 +557,104 @@ z +" id="mb12535d6a8" style="stroke:#000000;stroke-width:0.5;"/> - + +" id="m8a2e629618" style="stroke:#000000;stroke-width:0.5;"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -658,7 +662,7 @@ L -2 0 - + diff --git a/lib/matplotlib/tests/baseline_images/test_scale/logscale_mask.png b/lib/matplotlib/tests/baseline_images/test_scale/logscale_mask.png new file mode 100644 index 000000000000..0f142c315729 Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_scale/logscale_mask.png differ diff --git a/lib/matplotlib/tests/test_scale.py b/lib/matplotlib/tests/test_scale.py index 45ec7557ee88..e23ba8fcdd51 100644 --- a/lib/matplotlib/tests/test_scale.py +++ b/lib/matplotlib/tests/test_scale.py @@ -52,3 +52,16 @@ def test_logscale_subs(): ax.set_yscale('log', subsy=np.array([2, 3, 4])) # force draw fig.canvas.draw() + + +@image_comparison(baseline_images=['logscale_mask'], remove_text=True, + extensions=['png']) +def test_logscale_mask(): + # Check that zero values are masked correctly on log scales. + # See github issue 8045 + xs = np.linspace(0, 50, 1001) + + fig, ax = plt.subplots() + ax.plot(np.exp(-xs**2)) + fig.canvas.draw() + ax.set(yscale="log")