Mrg2.0.x #8110

Merged
merged 38 commits into from Feb 20, 2017
Commits
Jump to file
+998 −360
Split
View
@@ -10,6 +10,30 @@ out what caused the breakage and how to fix it by updating your code.
For new features that were added to Matplotlib, please see
:ref:`whats-new`.
+API Changes in 2.0.1
+====================
+
+Extensions to `matplotlib.backend_bases.GraphicsContextBase`
+------------------------------------------------------------
+
+To better support controlling the color of hatches, the method
+`matplotlib.backend_bases.GraphicsContextBase.set_hatch_color` was
+added to the expected API of ``GraphicsContext`` classes. Calls to
+this method are currently wrapped with a ``try:...except Attribute:``
+block to preserve back-compatibility with any third-party backends
+which do not extend `~matplotlib.backend_bases.GraphicsContextBase`.
+
+This value can be accessed in the backends via
+`matplotlib.backend_bases.GraphicsContextBase.get_hatch_color` (which
+was added in 2.0 see :ref:`gc_get_hatch_color_wn`) and should be used
+to color the hatches.
+
+In the future there may also be ``hatch_linewidth`` and
+``hatch_density`` related methods added. It is encouraged, but not
+required that third-party backends extend
+`~matplotlib.backend_bases.GraphicsContextBase` to make adapting to
+these changes easier.
+
API Changes in 2.0.0
====================
@@ -256,6 +256,12 @@ or by setting::
In your :file:`matplotlibrc` file.
+In addition, the ``forward`` kwarg to
+`~matplotlib.Figure.set_size_inches` now defaults to `True` to improve
+the interactive experience. Backend canvases that adjust the size of
+their bound `matplotlib.figure.Figure` must pass ``forward=False`` to
+avoid circular behavior. This default is not configurable.
+
Plotting functions
==================
@@ -624,20 +630,24 @@ To restore the previous behavior explicitly pass the keyword argument
Hatching
========
-The color and width of the lines in a hatch pattern are now configurable by the
-rcParams `hatch.color` and `hatch.linewidth`, with defaults of black and 1
-point, respectively. The old behaviour for the color was to apply the edge
-color or use black, depending on the artist; the old behavior for the line
-width was different depending on backend:
+
+The color of the lines in the hatch is now determined by
+
+ - If an edge color is explicitly set, use that for the hatch color
+ - If the edge color is not explicitly set, use ``rcParam['hatch.color']`` which
+ is looked up at artist creation time.
+
+The width of the lines in a hatch pattern is now configurable by the
+rcParams `hatch.linewidth`, which defaults to 1 point. The old
+behavior for the line width was different depending on backend:
- PDF: 0.1 pt
- SVG: 1.0 pt
- PS: 1 px
- Agg: 1 px
-The old color behavior can not be restored. The old line width behavior can not
-be restored across all backends simultaneously, but can be restored for a
-single backend by setting::
+The old line width behavior can not be restored across all backends
+simultaneously, but can be restored for a single backend by setting::
mpl.rcParams['hatch.linewidth'] = 0.1 # previous pdf hatch linewidth
mpl.rcParams['hatch.linewidth'] = 1.0 # previous svg hatch linewidth
@@ -650,7 +660,7 @@ The behavior of the PS and Agg backends was DPI dependent, thus::
mpl.rcParams['hatch.linewidth'] = 1.0 / dpi # previous ps and Agg hatch linewidth
-There is no API level control of the hatch color or linewidth.
+There is no direct API level control of the hatch color or linewidth.
Hatching patterns are now rendered at a consistent density, regardless of DPI.
Formerly, high DPI figures would be more dense than the default, and low DPI
View
@@ -313,6 +313,20 @@ value of ``None`` instead of ``2``. If ``None`` is given as ``zorder``,
:func:`streamplot` has a default ``zorder`` of
``matplotlib.lines.Line2D.zorder``.
+.. _gc_get_hatch_color_wn:
+
+Extension to `matplotlib.backend_bases.GraphicsContextBase`
+-----------------------------------------------------------
+
+To support standardizing hatch behavior across the backends we ship
+the `matplotlib.backend_bases.GraphicsContextBase.get_hatch_color`
+method as added to `matplotlib.backend_bases.GraphicsContextBase`.
+This is only used during the render process in the backends we ship so
+will not break any third-party backends.
+
+If you maintain a third-party backend which extends
+`~matplotlib.backend_bases.GraphicsContextBase` this method is now
+available to you and should be used to color hatch patterns.
Previous Whats New
==================
@@ -10,6 +10,7 @@ def samplemat(dims):
aa[i, i] = i
return aa
+
# Display matrix
plt.matshow(samplemat((15, 35)))
View
@@ -1384,8 +1384,8 @@ def __getitem__(self, key):
"Vega20b_r", "Vega20c", "Vega20c_r"]:
warn_deprecated(
"2.0",
- name="Vega colormaps",
- alternative="tab",
+ name=key,
+ alternative="tab" + key[4:],
obj_type="colormap"
)
@@ -2798,6 +2798,9 @@ def errorbar(self, x, y, yerr=None, xerr=None,
.. plot:: mpl_examples/statistics/errorbar_demo.py
"""
kwargs = cbook.normalize_kwargs(kwargs, _alias_map)
+ # anything that comes in as 'None', drop so the default thing
+ # happens down stream
+ kwargs = {k: v for k, v in kwargs.items() if v is not None}
kwargs.setdefault('zorder', 2)
if errorevery < 1:
@@ -838,6 +838,8 @@ def copy_properties(self, gc):
self._linewidth = gc._linewidth
self._rgb = gc._rgb
self._hatch = gc._hatch
+ self._hatch_color = gc._hatch_color
+ self._hatch_linewidth = gc._hatch_linewidth
self._url = gc._url
self._gid = gc._gid
self._snap = gc._snap
@@ -1123,6 +1125,12 @@ def get_hatch_color(self):
"""
return self._hatch_color
+ def set_hatch_color(self, hatch_color):
+ """
+ sets the color to use for hatching.
+ """
+ self._hatch_color = hatch_color
+
def get_hatch_linewidth(self):
"""
Gets the linewidth to use for hatching.
@@ -2253,14 +2253,14 @@ def alpha_cmd(self, alpha, forced, effective_alphas):
name = self.file.alphaState(effective_alphas)
return [name, Op.setgstate]
- def hatch_cmd(self, hatch):
+ def hatch_cmd(self, hatch, hatch_color):
if not hatch:
if self._fillcolor is not None:
return self.fillcolor_cmd(self._fillcolor)
else:
return [Name('DeviceRGB'), Op.setcolorspace_nonstroke]
else:
- hatch_style = (self._hatch_color, self._fillcolor, hatch)
+ hatch_style = (hatch_color, self._fillcolor, hatch)
name = self.file.hatchPattern(hatch_style)
return [Name('Pattern'), Op.setcolorspace_nonstroke,
name, Op.setcolor_nonstroke]
@@ -2324,7 +2324,8 @@ def clip_cmd(self, cliprect, clippath):
(('_linewidth',), linewidth_cmd),
(('_dashes',), dash_cmd),
(('_rgb',), rgb_cmd),
- (('_hatch',), hatch_cmd), # must come after fillcolor and rgb
+ # must come after fillcolor and rgb
+ (('_hatch', '_hatch_color'), hatch_cmd),
)
# TODO: _linestyle
@@ -2355,7 +2356,7 @@ def delta(self, other):
break
# Need to update hatching if we also updated fillcolor
- if params == ('_hatch',) and fill_performed:
+ if params == ('_hatch', '_hatch_color') and fill_performed:
different = True
if different:
@@ -131,6 +131,7 @@ def __init__(self,
self._linewidths = [0]
self._is_filled = True # May be modified by set_facecolor().
+ self._hatch_color = mcolors.to_rgba(mpl.rcParams['hatch.color'])
self.set_facecolor(facecolors)
self.set_edgecolor(edgecolors)
self.set_linewidth(linewidths)
@@ -260,6 +261,12 @@ def draw(self, renderer):
if self._hatch:
gc.set_hatch(self._hatch)
+ try:
+ gc.set_hatch_color(self._hatch_color)
+ except AttributeError:
+ # if we end up with a GC that does not have this method
+ warnings.warn("Your backend does not support setting the "
+ "hatch color.")
if self.get_sketch_params() is not None:
gc.set_sketch_params(*self.get_sketch_params())
@@ -648,12 +655,15 @@ def get_edgecolor(self):
get_edgecolors = get_edgecolor
def _set_edgecolor(self, c):
+ set_hatch_color = True
if c is None:
if (mpl.rcParams['patch.force_edgecolor'] or
not self._is_filled or self._edge_default):
c = mpl.rcParams['patch.edgecolor']
else:
c = 'none'
+ set_hatch_color = False
+
self._is_stroked = True
try:
if c.lower() == 'none':
@@ -668,6 +678,8 @@ def _set_edgecolor(self, c):
except AttributeError:
pass
self._edgecolors = mcolors.to_rgba_array(c, self._alpha)
+ if set_hatch_color and len(self._edgecolors):
+ self._hatch_color = tuple(self._edgecolors[0])
self.stale = True
def set_edgecolor(self, c):
View
@@ -679,15 +679,12 @@ def figimage(self, X,
return im
def set_size_inches(self, w, h=None, forward=True):
- """
- set_size_inches(w,h, forward=False)
-
- Set the figure size in inches (1in == 2.54cm)
+ """Set the figure size in inches (1in == 2.54cm)
- Usage::
+ Usage ::
fig.set_size_inches(w,h) # OR
- fig.set_size_inches((w,h) )
+ fig.set_size_inches((w,h))
optional kwarg *forward=True* will cause the canvas size to be
automatically updated; e.g., you can resize the figure window
@@ -1041,7 +1041,7 @@ class FontManager(object):
# Increment this version number whenever the font cache data
# format or behavior has changed and requires a existing font
# cache files to be rebuilt.
- __version__ = 200
+ __version__ = 201
def __init__(self, size=None, weight='normal'):
self._version = self.__version__
View
@@ -301,6 +301,10 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
if A is None:
raise RuntimeError('You must first set the image'
' array or the image attribute')
+ if any(s == 0 for s in A.shape):
+ raise RuntimeError("_make_image must get a non-empty image. "
+ "Your Artist's draw method must filter before "
+ "this method is called.")
clipped_bbox = Bbox.intersection(out_bbox, clip_bbox)
@@ -478,9 +482,17 @@ def _check_unsampled_image(self, renderer):
@allow_rasterization
def draw(self, renderer, *args, **kwargs):
+ # if not visible, declare victory and return
if not self.get_visible():
+ self.stale = False
return
+ # for empty images, there is nothing to draw!
+ if self.get_array().size == 0:
+ self.stale = False
+ return
+
+ # actually render the image.
gc = renderer.new_gc()
self._set_gc_clip(gc)
gc.set_alpha(self.get_alpha())
View
@@ -64,12 +64,12 @@ def _get_dash_pattern(style):
def _scale_dashes(offset, dashes, lw):
if not rcParams['lines.scale_dashes']:
return offset, dashes
- scale = max(2.0, lw)
+
scaled_offset = scaled_dashes = None
if offset is not None:
- scaled_offset = offset * scale
+ scaled_offset = offset * lw
if dashes is not None:
- scaled_dashes = [x * scale if x is not None else None
+ scaled_dashes = [x * lw if x is not None else None
for x in dashes]
return scaled_offset, scaled_dashes
View
@@ -5,6 +5,7 @@
import six
from six.moves import map, zip
+import warnings
import math
@@ -113,10 +114,10 @@ def __init__(self,
if antialiased is None:
antialiased = mpl.rcParams['patch.antialiased']
+ self._hatch_color = colors.to_rgba(mpl.rcParams['hatch.color'])
self._fill = True # needed for set_facecolor call
if color is not None:
if (edgecolor is not None or facecolor is not None):
- import warnings
warnings.warn("Setting the 'color' property will override"
"the edgecolor or facecolor properties. ")
self.set_color(color)
@@ -288,13 +289,18 @@ def set_aa(self, aa):
return self.set_antialiased(aa)
def _set_edgecolor(self, color):
+ set_hatch_color = True
if color is None:
if (mpl.rcParams['patch.force_edgecolor'] or
not self._fill or self._edge_default):
color = mpl.rcParams['patch.edgecolor']
else:
color = 'none'
+ set_hatch_color = False
+
self._edgecolor = colors.to_rgba(color, self._alpha)
+ if set_hatch_color:
+ self._hatch_color = self._edgecolor
self.stale = True
def set_edgecolor(self, color):
@@ -545,6 +551,12 @@ def draw(self, renderer):
if self._hatch:
gc.set_hatch(self._hatch)
+ try:
+ gc.set_hatch_color(self._hatch_color)
+ except AttributeError:
+ # if we end up with a GC that does not have this method
+ warnings.warn("Your backend does not have support for "
+ "setting the hatch color.")
if self.get_sketch_params() is not None:
gc.set_sketch_params(*self.get_sketch_params())
@@ -4265,6 +4277,13 @@ def draw(self, renderer):
if self._hatch:
gc.set_hatch(self._hatch)
+ if self._hatch_color is not None:
+ try:
+ gc.set_hatch_color(self._hatch_color)
+ except AttributeError:
+ # if we end up with a GC that does not have this method
+ warnings.warn("Your backend does not support setting the "
+ "hatch color.")
if self.get_sketch_params() is not None:
gc.set_sketch_params(*self.get_sketch_params())
@@ -963,9 +963,9 @@ def _validate_linestyle(ls):
'lines.solid_joinstyle': ['round', validate_joinstyle],
'lines.dash_capstyle': ['butt', validate_capstyle],
'lines.solid_capstyle': ['projecting', validate_capstyle],
- 'lines.dashed_pattern': [[2.8, 1.2], validate_nseq_float()],
- 'lines.dashdot_pattern': [[4.8, 1.2, 0.8, 1.2], validate_nseq_float()],
- 'lines.dotted_pattern': [[1.1, 1.1], validate_nseq_float()],
+ 'lines.dashed_pattern': [[3.7, 1.6], validate_nseq_float()],
+ 'lines.dashdot_pattern': [[6.4, 1.6, 1, 1.6], validate_nseq_float()],
+ 'lines.dotted_pattern': [[1, 1.65], validate_nseq_float()],
'lines.scale_dashes': [True, validate_bool],
# marker props
Oops, something went wrong.