|
4 | 4 | import six |
5 | 5 |
|
6 | 6 | from collections import OrderedDict, namedtuple |
| 7 | +import contextlib |
7 | 8 | from functools import wraps |
8 | 9 | import inspect |
9 | 10 | import re |
@@ -120,6 +121,22 @@ def __init__(self): |
120 | 121 | self._path_effects = rcParams['path.effects'] |
121 | 122 | self._sticky_edges = _XYPair([], []) |
122 | 123 |
|
| 124 | + # When plotting in log-scale, force the use of clip mode instead of |
| 125 | + # mask. The typical (internal) use case is log-scaled bar plots and |
| 126 | + # error bars. Ideally we'd want BarContainers / ErrorbarContainers |
| 127 | + # to have their own show() method which takes care of the patching, |
| 128 | + # but right now Containers are not taken into account during |
| 129 | + # the draw; instead their components (in the case of bar plots, |
| 130 | + # these are Rectangle patches; in the case of ErrorbarContainers, |
| 131 | + # LineCollections) are drawn individually, so tracking the force_clip |
| 132 | + # state must be done by the component artists. Note that handling of |
| 133 | + # _force_clip_in_log_scale must be done by the individual artists' |
| 134 | + # draw implementation; right now only Patches and Collections support |
| 135 | + # it. The `_forcing_clip_in_log_scale` decorator may be helpful to |
| 136 | + # implement such support, it should typically be applied around a call |
| 137 | + # to `transform_path_non_affine`. |
| 138 | + self._force_clip_in_log_scale = False |
| 139 | + |
123 | 140 | def __getstate__(self): |
124 | 141 | d = self.__dict__.copy() |
125 | 142 | # remove the unpicklable remove method, this will get re-added on load |
@@ -779,6 +796,21 @@ def draw(self, renderer, *args, **kwargs): |
779 | 796 | return |
780 | 797 | self.stale = False |
781 | 798 |
|
| 799 | + @contextlib.contextmanager |
| 800 | + def _forcing_clip_in_log_scale(self): |
| 801 | + # See _force_clip_in_log_scale for explanation. |
| 802 | + fvs = {} |
| 803 | + if self._force_clip_in_log_scale and self.axes: |
| 804 | + for axis in self.axes._get_axis_list(): |
| 805 | + if axis.get_scale() == "log": |
| 806 | + fvs[axis] = axis._scale._transform._fill_value |
| 807 | + axis._scale._transform._fill_value = 1e-300 |
| 808 | + try: |
| 809 | + yield |
| 810 | + finally: |
| 811 | + for axis, fv in fvs.items(): |
| 812 | + axis._scale._transform._fill_value = fv |
| 813 | + |
782 | 814 | def set_alpha(self, alpha): |
783 | 815 | """ |
784 | 816 | Set the alpha value used for blending - not supported on |
|
0 commit comments