8000 Add more logic and a new test · matplotlib/matplotlib@d852897 · GitHub
[go: up one dir, main page]

Skip to content

Commit d852897

Browse files
committed
Add more logic and a new test
1 parent 29bd9c2 commit d852897

File tree

2 files changed

+88
-42
lines changed

2 files changed

+88
-42
lines changed

lib/matplotlib/collections.py

Lines changed: 58 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def __init__(self,
171171
# Flags: do colors come from mapping an array?
172172
self._face_is_mapped = True
173173
self._edge_is_mapped = False
174-
174+
self._mapped_colors = None # Calculated in update_scalarmappable
175175
self._hatch_color = mcolors.to_rgba(mpl.rcParams['hatch.color'])
176176
self.set_facecolor(facecolors)
177177
self.set_edgecolor(edgecolors)
@@ -853,57 +853,74 @@ def get_linestyle(self):
853853
return self._linestyles
854854

855855
def _set_mappable_flags(self):
856+
edge0 = self._edge_is_mapped
857+
face0 = self._face_is_mapped
856858
if self._A is None:
857859
self._edge_is_mapped = False
858860
self._face_is_mapped = False
859-
return False # Nothing to map
860-
861-
# Typical mapping: centers, not edges.
862-
self._face_is_mapped = True
863-
self._edge_is_mapped = False
864-
865-
# Make the colors None or a string. (If None, it is a default.)
866-
fc = self._original_facecolor
867-
if not (fc is None or isinstance(fc, str)):
868-
fc = 'array'
869-
ec = self._original_edgecolor
870-
if not(ec is None or isinstance(ec, str)):
871-
ec = 'array'
861+
# return False # Nothing to map
862+
else:
863+
# Typical mapping: centers, not edges.
864+
self._face_is_mapped = True
865+
self._edge_is_mapped = False
872866

873-
# Handle special cases.
874-
if fc == 'none':
875-
self._face_is_mapped = False
876-
if ec in ('face', 'none', None):
877-
self._edge_is_mapped = True
878-
if ec == 'face':
879-
self._edge_is_mapped = self._face_is_mapped
880-
return self._face_is_mapped or self._edge_is_mapped
867+
# Make the colors None or a string. (If None, it is a default.)
868+
fc = self._original_facecolor
869+
if not (fc is None or isinstance(fc, str)):
870+
fc = 'array'
871+
ec = self._original_edgecolor
872+
if not (ec is None or isinstance(ec, str)):
873+
ec = 'array'
874+
875+
# Handle special cases.
876+
if fc == 'none':
877+
self._face_is_mapped = False
878+
if ec in ('face', 'none', None):
879+
self._edge_is_mapped = True
880+
if ec == 'face':
881+
self._edge_is_mapped = self._face_is_mapped
882+
883+
mapped = self._face_is_mapped or self._edge_is_mapped
884+
changed = (self._edge_is_mapped != edge0
885+
or self._face_is_mapped != face0)
886+
return mapped or changed
881887

882888
def update_scalarmappable(self):
883-
"""Update colors from the scalar mappable array, if any."""
889+
"""
890+
Update colors from the scalar mappable array, if any.
891+
892+
Assign colors to edges and faces based on the array and/or
893+
colors that were directly set, as appropriate.
894+
"""
884895
if not self._set_mappable_flags():
885896
return
886-
# QuadMesh can map 2d arrays (but pcolormesh supplies 1d array)
887-
if self._A.ndim > 1 and not isinstance(self, QuadMesh):
888-
raise ValueError('Collections can only map rank 1 arrays')
889-
if not self._check_update("array"):
890-
return
891-
if np.iterable(self._alpha):
892-
if self._alpha.size != self._A.size:
893-
raise ValueError(f'Data array shape, {self._A.shape} '
894-
'is incompatible with alpha array shape, '
895-
f'{self._alpha.shape}. '
896-
'This can occur with the deprecated '
897-
'behavior of the "flat" shading option, '
898-
'in which a row and/or column of the data '
899-
'array is dropped.')
900-
# pcolormesh, scatter, maybe others flatten their _A
901-
self._alpha = self._alpha.reshape(self._A.shape)
897+
# Allow possibility to call 'self.set_array(None)'.
898+
if self._check_update("array") and self._A is not None:
899+
# QuadMesh can map 2d arrays (but pcolormesh supplies 1d array)
900+
if self._A.ndim > 1 and not isinstance(self, QuadMesh):
901+
raise ValueError('Collections can only map rank 1 arrays')
902+
if np.iterable(self._alpha):
903+
if self._alpha.size != self._A.size:
904+
raise ValueError(
905+
f'Data array shape, {self._A.shape} '
906+
'is incompatible with alpha array shape, '
907+
f'{self._alpha.shape}. '
908+
'This can occur with the deprecated '
909+
'behavior of the "flat" shading option, '
910+
'in which a row and/or column of the data '
911+
'array is dropped.')
912+
# pcolormesh, scatter, maybe others flatten their _A
913+
self._alpha = self._alpha.reshape(self._A.shape)
914+
self._mapped_colors = self.to_rgba(self._A, self._alpha)
902915

903916
if self._face_is_mapped:
904-
self._facecolors = self.to_rgba(self._A, self._alpha)
917+
self._facecolors = self._mapped_colors
918+
else:
919+
self._set_facecolor(self._original_facecolor)
905920
if self._edge_is_mapped:
906-
self._edgecolors = self.to_rgba(self._A, self._alpha)
921+
self._edgecolors = self._mapped_colors
922+
else:
923+
self._set_edgecolor(self._original_edgecolor)
907924
self.stale = True
908925

909926
@cbook.deprecated("3.4")
@@ -1881,7 +1898,6 @@ def __init__(self, triangulation, **kwargs):
18811898
super().__init__(**kwargs)
18821899
self._triangulation = triangulation
18831900
self._shading = 'gouraud'
1884-
self._face_is_mapped = True
18851901

18861902
self._bbox = transforms.Bbox.unit()
18871903

lib/matplotlib/tests/test_collections.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,3 +747,33 @@ def test_legend_inverse_size_label_relationship():
747747
handle_sizes = [5 / x**2 for x in handle_sizes]
748748

749749
assert_array_almost_equal(handle_sizes, legend_sizes, decimal=1)
750+
751+
752+
@pytest.mark.parametrize('pcfunc', [plt.pcolor, plt.pcolormesh])
753+
def test_color_logic(pcfunc):
754+
z = np.arange(12).reshape(3, 4)
755+
pc = pcfunc(z, edgecolors='red', facecolors='none')
756+
assert_array_equal(pc.get_edgecolor(), [[1, 0, 0, 1]])
757+
# Check setting attributes after initialization:
758+
pc = pcfunc(z)
759+
pc.set_facecolor('none')
760+
pc.set_edgecolor('red')
761+
assert_array_equal(pc.get_edgecolor(), [[1, 0, 0, 1]])
762+
pc.set_alpha(0.5)
763+
assert_array_equal(pc.get_edgecolor(), [[1, 0, 0, 0.5]])
764+
pc.set_edgecolor(None)
765+
pc.update_scalarmappable()
766+
assert pc.get_edgecolor().shape == (12, 4) # color-mapped
767+
pc.set_facecolor(None)
768+
pc.update_scalarmappable()
769+
assert pc.get_facecolor().shape == (12, 4) # color-mapped
770+
assert pc.get_edgecolor().shape == (1, 4) # no longer color-mapped
771+
# Turn off colormapping entirely:
772+
pc.set_array(None)
773+
pc.update_scalarmappable()
774+
assert pc.get_facecolor().shape == (1, 4) # no longer color-mapped
775+
# Turn it back on by restoring the array (must be 1D!):
776+
pc.set_array(z.ravel())
777+
pc.update_scalarmappable()
778+
assert pc.get_facecolor().shape == (12, 4) # color-mapped
779+
assert pc.get_edgecolor().shape == (1, 4) # not color-mapped

0 commit comments

Comments
 (0)
0