8000 Rename To Mapper and reorganizatino · matplotlib/matplotlib@7f6fe56 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7f6fe56

Browse files
committed
Rename To Mapper and reorganizatino
1 parent c4925ec commit 7f6fe56

File tree

9 files changed

+353
-251
lines changed

9 files changed

+353
-251
lines changed

lib/matplotlib/artist.py

Lines changed: 120 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212
import numpy as np
1313

1414
import matplotlib as mpl
15-
from . import _api, cbook
16-
from .colors import BoundaryNorm, BivarColormap
17-
from .cm import VectorMappable
15+
from . import _api, cbook, cm
16+
from .cm import ScalarMappable
1817
from .path import Path
1918
from .transforms import (BboxBase, Bbox, IdentityTransform, Transform, TransformedBbox,
2019
TransformedPatchPath, TransformedPath)
@@ -1346,49 +1345,16 @@ def format_cursor_data(self, data):
13461345
--------
13471346
get_cursor_data
13481347
"""
1349-
if isinstance(self, VectorMappable) and \
1350-
(np.ndim(data) == 0 or len(data) == self.cmap.n_variates):
1351-
# This block logically belongs to VectorMappable, but can't be
1352-
# implemented in it because most VectorMappable subclasses
1353-
# inherit from Artist first and from VectorMappable second, so
1348+
if isinstance(self, ScalarMappable):
1349+
# Internal classes no longer inherit from ScalarMappable, and this
1350+
# block should never be executed by the internal API
1351+
1352+
# This block logically belongs to ScalarMappable, but can't be
1353+
# implemented in it in case custom ScalarMappable subclasses
1354+
# inherit from Artist first and from ScalarMappable second, so
13541355
# Artist.format_cursor_data would always have precedence over
1355-
# VectorMappable.format_cursor_data.
1356-
if self.cmap.n_variates == 1:
1357-
data = [data]
1358-
# The above if test is equivalent to `isinstance(self.cmap, Colormap)`
1359-
num_colors = [self.cmap.N]
1360-
else:
1361-
if isinstance(self.cmap, BivarColormap):
1362-
num_colors = [self.cmap.N, self.cmap.M]
1363-
else: # i.e. a MultivarColormap object
1364-
num_colors = [component.N for component in self.cmap]
1365-
1366-
out_str = '['
1367-
for nn, dd, nc in zip(self.nac._norm, data, num_colors):
1368-
if np.ma.getmask(dd):
1369-
out_str += ", "
1370-
else:
1371-
# Figure out a reasonable amount of significant digits
1372-
normed = nn(dd)
1373-
if np.isfinite(normed):
1374-
if isinstance(nn, BoundaryNorm):
1375-
# not an invertible normalization mapping
1376-
cur_idx = np.argmin(np.abs(nn.boundaries - dd))
1377-
neigh_idx = max(0, cur_idx - 1)
1378-
# use max diff to prevent delta == 0
1379-
delta = np.diff(
1380-
nn.boundaries[neigh_idx:cur_idx + 2]
1381-
).max()
1382-
else:
1383-
# Midpoints of neighboring color intervals.
1384-
neighbors = nn.inverse(
1385-
(int(normed * nc) + np.array([0, 1])) / nc)
1386-
delta = abs(neighbors - dd).max()
1387-
g_sig_digits = cbook._g_sig_digits(dd, delta)
1388-
else:
1389-
g_sig_digits = 3 # Consistent with default below.
1390-
out_str += f"{dd:-#.{g_sig_digits}g}, "
1391-
return out_str[:-2] + ']'
1356+
# ScalarMappable.format_cursor_data.
1357+
return self.mapper._format_cursor_data(data)
13921358
else:
13931359
try:
13941360
data[0]
@@ -1431,6 +1397,115 @@ def set_mouseover(self, mouseover):
14311397
mouseover = property(get_mouseover, set_mouseover) # backcompat.
14321398

14331399

1400+
class ColorableArtist(Artist):
1401+
def __init__(self, norm=None, cmap=None):
1402+
"""
1403+
Parameters
1404+
----------
1405+
norm : `.Normalize` (or subclass thereof) or str or None
1406+
The normalizing object which scales data, typically into the
1407+
interval ``[0, 1]``.
1408+
If a `str`, a `.Normalize` subclass is dynamically generated based
1409+
on the scale with the corresponding name.
1410+
If *None*, *norm* defaults to a *colors.Normalize* object which
1411+
initializes its scaling based on the first data processed.
1412+
cmap : str or `~matplotlib.colors.Colormap`
1413+
The colormap used to map normalized data values to RGBA colors.
1414+
"""
1415+
1416+
Artist.__init__(self)
1417+
1418+
self._A = None
1419+
if isinstance(norm, cm.Mapper):
1420+
self._mapper = norm
1421+
else:
1422+
self._mapper = cm.Mapper(cmap, norm)
1423+
1424+
self._id_mapper = self.mapper.callbacks.connect('changed', self.changed)
1425+
self.callbacks = cbook.CallbackRegistry(signals=["changed"])
1426+
1427+
def set_array(self, A):
1428+
"""
1429+
Set the value array from array-like *A*.
1430+
1431+
Parameters
1432+
----------
1433+
A : array-like or None
1434+
The values that are mapped to colors.
1435+
1436+
The base class `.VectorMappable` does not make any assumptions on
1437+
the dimensionality and shape of the value array *A*.
1438+
"""
1439+
if A is None:
1440+
self._A = None
1441+
return
1442+
A = cm._ensure_multivariate_data(self.cmap.n_variates, A)
1443+
1444+
A = cbook.safe_masked_invalid(A, copy=True)
1445+
if not np.can_cast(A.dtype, float, "same_kind"):
1446+
if A.dtype.fields is None:
1447+
raise TypeError(f"Image data of dtype {A.dtype} cannot be "
1448+
f"converted to float")
1449+
else:
1450+
for key in A.dtype.fields:
1451+
if not np.can_cast(A[key].dtype, float, "same_kind"):
1452+
raise TypeError(f"Image data of dtype {A.dtype} cannot be "
1453+
f"converted to a sequence of floats")
1454+
self._A = A
1455+
self.mapper.autoscale_None(A)
1456+
1457+
@property
1458+
def mapper(self):
1459+
return self._mapper
1460+
1461+
@mapper.setter
1462+
def mapper(self, mapper):
1463+
self._set_mapper(mapper)
1464+
1465+
def _set_mapper(self, mapper):
1466+
if isinstance(mapper, cm.Mapper):
1467+
if self._A is not None:
1468+
if not mapper.n_variates == self.mapper.n_variates:
1469+
raise ValueError('The new Mapper object must have the same'
1470+
' number of variates as the existing data.')
1471+
else:
1472+
self.mapper.callbacks.disconnect(self._id_mapper)
1473+
self._mapper = mapper
1474+
self._id_mapper = mapper.callbacks.connect('changed', self.changed)
1475+
self.changed()
1476+
else:
1477+
raise ValueError('Only a Mapper object can be set to mapper.')
1478+
1479+
def get_array(self):
1480+
"""
1481+
Return the array of values, that are mapped to colors.
1482+
1483+
The base class `.VectorMappable` does not make any assumptions on
1484+
the dimensionality and shape of the array.
1485+
"""
1486+
return self._A
1487+
1488+
def changed(self):
1489+
"""
1490+
Call this whenever the mappable is changed to notify all the
1491+
callbackSM listeners to the 'changed' signal.
1492+
"""
1493+
self.callbacks.process('changed')
1494+
self.stale = True
1495+
1496+
def format_cursor_data(self, data):
1497+
"""
1498+
Return a string representation of *data*.
1499+
1500+
Uses the colorbar's formatter to format the data.
1501+
1502+
See Also
1503+
--------
1504+
get_cursor_data
1505+
"""
1506+
return self.mapper._format_cursor_data(data)
1507+
1508+
14341509
def _get_tightbbox_for_layout_only(obj, *args, **kwargs):
14351510
"""
14361511
Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a

lib/matplotlib/backends/qt_editor/figureoptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ def prepare_data(d, init):
160160
cvals = cm._multivar_colormaps.values()
161161
if cmap not in cvals:
162162
cmaps = [(cmap, cmap.name), *cmaps]
163-
low, high = mappable.nac.get_clim()
163+
low, high = mappable.mapper.get_clim()
164164
if len(low) == 1:
165165
low = low[0]
166166
high = high[0]

0 commit comments

Comments
 (0)
0