Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7998c60

Browse filesBrowse files
committed
simple wrapper on boundarynorm + listed colormap
1 parent 12cafa9 commit 7998c60
Copy full SHA for 7998c60

File tree

6 files changed

+230
-227
lines changed
Filter options

6 files changed

+230
-227
lines changed

‎.travis.yml

Copy file name to clipboardExpand all lines: .travis.yml
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ install:
110110
# Install nose from a build which has partial
111111
# support for python36 and suport for coverage output suppressing
112112
pip install git+https://github.com/jenshnielsen/nose.git@matplotlibnose
113-
113+
pip install pytest
114114
# We manually install humor sans using the package from Ubuntu 14.10. Unfortunatly humor sans is not
115115
# availible in the Ubuntu version used by Travis but we can manually install the deb from a later
116116
# version since is it basically just a .ttf file

‎appveyor.yml

Copy file name to clipboardExpand all lines: appveyor.yml
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ install:
8282
# same things as the requirements in ci/conda_recipe/meta.yaml
8383
# if conda-forge gets a new pyqt, it might be nice to install it as well to have more backends
8484
# https://github.com/conda-forge/conda-forge.github.io/issues/157#issuecomment-223536381
85-
- cmd: conda create -q -n test-environment python=%PYTHON_VERSION% pip setuptools numpy python-dateutil freetype=2.6 msinttypes "tk=8.5" pyparsing pytz tornado "libpng>=1.6.21,<1.7" "zlib=1.2" "cycler>=0.10" nose mock
85+
- cmd: conda create -q -n test-environment python=%PYTHON_VERSION% pip setuptools numpy python-dateutil freetype=2.6 msinttypes "tk=8.5" pyparsing pytz tornado "libpng>=1.6.21,<1.7" "zlib=1.2" "cycler>=0.10" nose mock pytest
8686
- activate test-environment
8787
- cmd: echo %PYTHON_VERSION% %TARGET_ARCH%
8888
- cmd: IF %PYTHON_VERSION% == 2.7 conda install -q functools32

‎lib/matplotlib/axis.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axis.py
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ def __init__(self, axes, pickradius=15):
642642
self.offsetText = self._get_offset_text()
643643
self.majorTicks = []
644644
self.minorTicks = []
645-
self.unit_data = []
645+
self.unit_data = None
646646
self.pickradius = pickradius
647647

648648
# Initialize here for testing; later add API
@@ -695,14 +695,14 @@ def limit_range_for_scale(self, vmin, vmax):
695695

696696
@property
697697
def unit_data(self):
698-
"""Holds data that a ConversionInterface subclass relys on
698+
"""Holds data that a ConversionInterface subclass uses
699699
to convert between labels and indexes
700700
"""
701701
return self._unit_data
702702

703703
@unit_data.setter
704-
def unit_data(self, data):
705-
self._unit_data = data
704+
def unit_data(self, unit_data):
705+
self._unit_data = unit_data
706706

707707
def get_children(self):
708708
children = [self.label, self.offsetText]

‎lib/matplotlib/category.py

Copy file name to clipboardExpand all lines: lib/matplotlib/category.py
+79-63Lines changed: 79 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
"""
55
from __future__ import (absolute_import, division, print_function,
66
unicode_literals)
7-
87
import six
98

109
import numpy as np
1110

11+
import matplotlib.cbook as cbook
12+
import matplotlib.colors as mcolors
1213
import matplotlib.units as units
1314
import matplotlib.ticker as ticker
1415

@@ -22,10 +23,12 @@
2223
def to_array(data, maxlen=100):
2324
if NP_NEW:
2425
return np.array(data, dtype=np.unicode)
26+
if cbook.is_scalar_or_string(data):
27+
data = [data]
2528
try:
2629
vals = np.array(data, dtype=('|S', maxlen))
2730
except UnicodeEncodeError:
28-
# pure hack
31+
# this yields gibberish
2932
vals = np.array([convert_to_string(d) for d in data])
3033
return vals
3134

@@ -36,49 +39,83 @@ def convert(value, unit, axis):
3639
"""Uses axis.unit_data map to encode
3740
data as floats
3841
"""
39-
vmap = dict(axis.unit_data)
42+
vmap = dict(zip(axis.unit_data.seq, axis.unit_data.locs))
4043

4144
if isinstance(value, six.string_types):
4245
return vmap[value]
4346

4447
vals = to_array(value)
45-
for lab, loc in axis.unit_data:
48+
for lab, loc in vmap.items():
4649
vals[vals == lab] = loc
4750

4851
return vals.astype('float')
4952

5053
@staticmethod
5154
def axisinfo(unit, axis):
52-
seq, locs = zip(*axis.unit_data)
53-
majloc = StrCategoryLocator(locs)
54-
majfmt = StrCategoryFormatter(seq)
55+
majloc = StrCategoryLocator(axis.unit_data.locs)
56+
majfmt = StrCategoryFormatter(axis.unit_data.seq)
5557
return units.AxisInfo(majloc=majloc, majfmt=majfmt)
5658

5759
@staticmethod
5860
def default_units(data, axis):
5961
# the conversion call stack is:
6062
# default_units->axis_info->convert
61-
axis.unit_data = map_categories(data, axis.unit_data)
63+
if axis.unit_data is None:
64+
axis.unit_data = UnitData(data)
65+
else:
66+
axis.unit_data.update(data)
6267
return None
6368

6469

6570
class StrCategoryLocator(ticker.FixedLocator):
6671
def __init__(self, locs):
67-
super(StrCategoryLocator, self).__init__(locs, None)
72+
self.locs = locs
73+
self.nbins = None
6874

6975

7076
class StrCategoryFormatter(ticker.FixedFormatter):
7177
def __init__(self, seq):
72-
super(StrCategoryFormatter, self).__init__(seq)
78+
self.seq = seq
79+
self.offset_string = ''
80+
81+
82+
def colors_from_categories(codings):
83+
"""
84+
A helper routine to generate a cmap and a norm instance where
85+
a given key in coding is associated with a color value in coding
86+
87+
Parameters
88+
----------
89+
coding : sequence of [(key, value)] pairs where key is the
90+
categorical variable, and value is its associated
91+
color
92+
93+
Returns
94+
-------
95+
(cmap, norm) : tuple containing a :class:`Colormap` and a \
96+
:class:`Normalize` instance
97+
"""
98+
if isinstance(codings, dict):
99+
codings = codings.items()
100+
if six.PY3:
101+
codings = list(codings)
102+
103+
codings.sort()
104+
105+
cats, cols = zip(*codings)
106+
cmap = mcolors.ListedColormap(cols)
107+
cats = list(cats) + [np.inf]
108+
norm = mcolors.BoundaryNorm(cats, cmap.N)
109+
return cmap, norm
73110

74111

75112
def convert_to_string(value):
76113
"""Helper function for numpy 1.6, can be replaced with
77114
np.array(...,dtype=unicode) for all later versions of numpy"""
78115

79116
if isinstance(value, six.string_types):
80-
return value
81-
if np.isfinite(value):
117+
pass
118+
elif np.isfinite(value):
82119
value = np.asarray(value, dtype=str)[np.newaxis][0]
83120
elif np.isnan(value):
84121
value = 'nan'
@@ -91,59 +128,38 @@ def convert_to_string(value):
91128
return value
92129

93130

94-
def map_categories(data, old_map=None):
95-
"""Create mapping between unique categorical
96-
values and numerical identifier.
97-
98-
Paramters
99-
---------
100-
data: iterable
101-
sequence of values
102-
old_map: list of tuple, optional
103-
if not `None`, than old_mapping will be updated with new values and
104-
previous mappings will remain unchanged)
105-
sort: bool, optional
106-
sort keys by ASCII value
107-
108-
Returns
109-
-------
110-
list of tuple
111-
[(label, ticklocation),...]
112-
113-
"""
114-
115-
# code typical missing data in the negative range because
116-
# everything else will always have positive encoding
117-
# question able if it even makes sense
131+
class UnitData(object):
132+
# debatable makes sense to special code missing values
118133
spdict = {'nan': -1.0, 'inf': -2.0, '-inf': -3.0}
119134

120-
if isinstance(data, six.string_types):
121-
data = [data]
122-
123-
# will update this post cbook/dict support
124-
strdata = to_array(data)
125-
uniq = np.unique(strdata)
126-
127-
if old_map:
128-
olabs, okeys = zip(*old_map)
129-
svalue = max(okeys) + 1
130-
else:
131-
old_map, olabs, okeys = [], [], []
132-
svalue = 0
133-
134-
category_map = old_map[:]
135-
136-
new_labs = [u for u in uniq if u not in olabs]
137-
missing = [nl for nl in new_labs if nl in spdict.keys()]
138-
139-
category_map.extend([(m, spdict[m]) for m in missing])
140-
141-
new_labs = [nl for nl in new_labs if nl not in missing]
142-
143-
new_locs = np.arange(svalue, svalue + len(new_labs), dtype='float')
144-
category_map.extend(list(zip(new_labs, new_locs)))
145-
return category_map
146-
135+
def __init__(self, data):
136+
"""Create mapping between unique categorical values
137+
and numerical identifier
138+
Paramters
139+
---------
140+
data: iterable
141+
sequence of values
142+
"""
143+
self.seq, self.locs = [], []
144+
self._set_seq_locs(data, 0)
145+
146+
def update(self, new_data):
147+
# so as not to conflict with spdict
148+
value = max(max(self.locs) + 1, 0)
149+
self._set_seq_locs(new_data, value)
150+
151+
def _set_seq_locs(self, data, value):
152+
# magic to make it work under np1.6
153+
strdata = to_array(data)
154+
# np.unique makes dateframes work
155+
new_s = [d for d in np.unique(strdata) if d not in self.seq]
156+
for ns in new_s:
157+
self.seq.append(convert_to_string(ns))
158+
if ns in UnitData.spdict.keys():
159+
self.locs.append(UnitData.spdict[ns])
160+
else:
161+
self.locs.append(value)
162+
value += 1
147163

148164
# Connects the convertor to matplotlib
149165
units.registry[str] = StrCategoryConverter()

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.