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 41822d5

Browse filesBrowse files
committed
Merge pull request #1057 from efiring/contour_norm_scaling
Contour norm scaling
2 parents 50ae794 + 0890246 commit 41822d5
Copy full SHA for 41822d5

File tree

Expand file treeCollapse file tree

12 files changed

+20367
-170
lines changed
Filter options
Expand file treeCollapse file tree

12 files changed

+20367
-170
lines changed

‎CHANGELOG

Copy file name to clipboardExpand all lines: CHANGELOG
+9-1Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1+
2012-08-05 When a norm is passed to contourf, either or both of the
2+
vmin, vmax attributes of that norm are now respected.
3+
Formerly they were respected only if both were
4+
specified. In addition, vmin and/or vmax can now
5+
be passed to contourf directly as kwargs. - EF
6+
17
2012-07-24 Contourf handles the extend kwarg by mapping the extended
28
ranges outside the normed 0-1 range so that they are
39
handled by colormap colors determined by the set_under
410
and set_over methods. Previously the extended ranges
511
were mapped to 0 or 1 so that the "under" and "over"
6-
colormap colors were ignored. - EF
12+
colormap colors were ignored. This change also increases
13+
slightly the color contrast for a given set of contour
14+
levels. - EF
715

816
2012-06-24 Make use of mathtext in tick labels configurable - DSD
917

‎lib/matplotlib/axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes.py
+16-16Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3754,7 +3754,7 @@ def vlines(self, x, ymin, ymax, colors='k', linestyles='solid',
37543754
linestyles=linestyles, label=label)
37553755
self.add_collection(coll)
37563756
coll.update(kwargs)
3757-
3757+
37583758
if len(x) > 0:
37593759
minx = min( x )
37603760
maxx = max( x )
@@ -6955,16 +6955,18 @@ def pcolor(self, *args, **kwargs):
69556955
A :class:`matplotlib.colors.Colormap` instance. If *None*, use
69566956
rc settings.
69576957
6958-
norm: [ *None* | Normalize ]
6958+
*norm*: [ *None* | Normalize ]
69596959
An :class:`matplotlib.colors.Normalize` instance is used
69606960
to scale luminance data to 0,1. If *None*, defaults to
69616961
:func:`normalize`.
69626962
69636963
*vmin*/*vmax*: [ *None* | scalar ]
69646964
*vmin* and *vmax* are used in conjunction with *norm* to
6965-
normalize luminance data. If either are *None*, the min
6966-
and max of the color array *C* is used. If you pass a
6967-
*norm* instance, *vmin* and *vmax* will be ignored.
6965+
normalize luminance data. If either is *None*, it
6966+
is autoscaled to the respective min or max
6967+
of the color array *C*. If not *None*, *vmin* or
6968+
*vmax* passed in here override any pre-existing values
6969+
supplied in the *norm* instance.
69686970
69696971
*shading*: [ 'flat' | 'faceted' ]
69706972
If 'faceted', a black grid is drawn around each rectangle; if
@@ -7121,10 +7123,8 @@ def pcolor(self, *args, **kwargs):
71217123
if norm is not None: assert(isinstance(norm, mcolors.Normalize))
71227124
collection.set_cmap(cmap)
71237125
collection.set_norm(norm)
7124-
if vmin is not None or vmax is not None:
7125-
collection.set_clim(vmin, vmax)
7126-
else:
7127-
collection.autoscale_None()
7126+
collection.set_clim(vmin, vmax)
7127+
collection.autoscale_None()
71287128
self.grid(False)
71297129

71307130
x = X.compressed()
@@ -7167,9 +7167,11 @@ def pcolormesh(self, *args, **kwargs):
71677167
71687168
*vmin*/*vmax*: [ *None* | scalar ]
71697169
*vmin* and *vmax* are used in conjunction with *norm* to
7170-
normalize luminance data. If either are *None*, the min
7171-
and max of the color array *C* is used. If you pass a
7172-
*norm* instance, *vmin* and *vmax* will be ignored.
7170+
normalize luminance data. If either is *None*, it
7171+
is autoscaled to the respective min or max
7172+
of the color array *C*. If not *None*, *vmin* or
7173+
*vmax* passed in here override any pre-existing values
7174+
supplied in the *norm* instance.
71737175
71747176
*shading*: [ 'flat' | 'gouraud' ]
71757177
'flat' indicates a solid color for each quad. When
@@ -7235,10 +7237,8 @@ def pcolormesh(self, *args, **kwargs):
72357237
if norm is not None: assert(isinstance(norm, mcolors.Normalize))
72367238
collection.set_cmap(cmap)
72377239
collection.set_norm(norm)
7238-
if vmin is not None or vmax is not None:
7239-
collection.set_clim(vmin, vmax)
7240-
else:
7241-
collection.autoscale_None()
7240+
collection.set_clim(vmin, vmax)
7241+
collection.autoscale_None()
72427242

72437243
self.grid(False)
72447244

‎lib/matplotlib/colorbar.py

Copy file name to clipboardExpand all lines: lib/matplotlib/colorbar.py
+46-28Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ def __init__(self, ax, cmap=None,
255255
self.filled = filled
256256
self.extendfrac = extendfrac
257257
self.solids = None
258-
self.lines = None
258+
self.lines = list()
259259
self.outline = None
260260
self.patch = None
261261
self.dividers = None
@@ -467,14 +467,25 @@ def _add_solids(self, X, Y, C):
467467
)
468468
self.ax.add_collection(self.dividers)
469469

470-
def add_lines(self, levels, colors, linewidths):
470+
def add_lines(self, levels, colors, linewidths, erase=True):
471471
'''
472472
Draw lines on the colorbar.
473+
474+
*colors* and *linewidths* must be scalars or
475+
sequences the same length as *levels*.
476+
477+
Set *erase* to False to add lines without first
478+
removing any previously added lines.
473479
'''
474-
N = len(levels)
475-
dummy, y = self._locate(levels)
476-
if len(y) != N:
477-
raise ValueError("levels are outside colorbar range")
480+
y = self._locate(levels)
481+
nlevs = len(levels)
482+
igood = (y < 1.001) & (y > -0.001)
483+
y = y[igood]
484+
if cbook.iterable(colors):
485+
colors = np.asarray(colors)[igood]
486+
if cbook.iterable(linewidths):
487+
linewidths = np.asarray(linewidths)[igood]
488+
N = len(y)
478489
x = np.array([0.0, 1.0])
479490
X, Y = np.meshgrid(x,y)
480491
if self.orientation == 'vertical':
@@ -483,9 +494,10 @@ def add_lines(self, levels, colors, linewidths):
483494
xy = [zip(Y[i], X[i]) for i in xrange(N)]
484495
col = collections.LineCollection(xy, linewidths=linewidths)
485496

486-
if self.lines:
487-
self.lines.remove()
488-
self.lines = col
497+
if erase and self.lines:
498+
for lc in self.lines.pop():
499+
lc.remove()
500+
self.lines.append(col)
489501
col.set_color(colors)
490502
self.ax.add_collection(col)
491503

@@ -528,7 +540,10 @@ def _ticker(self):
528540
locator.axis.get_minpos = lambda : intv[0]
529541
formatter.axis.get_minpos = lambda : intv[0]
530542
b = np.array(locator())
531-
b, ticks = self._locate(b)
543+
ticks = self._locate(b)
544+
inrange = (ticks > -0.001) & (ticks < 1.001)
545+
ticks = ticks[inrange]
546+
b = b[inrange]
532547
formatter.set_locs(b)
533548
ticklabels = [formatter(t, i) for i, t in enumerate(b)]
534549
offset_string = formatter.get_offset()
@@ -746,37 +761,36 @@ def _mesh(self):
746761

747762
def _locate(self, x):
748763
'''
749-
Given a possible set of color data values, return the ones
750-
within range, together with their corresponding colorbar
751-
data coordinates.
764+
Given a set of color data values, return their
765+
corresponding colorbar data coordinates.
752766
'''
753767
if isinstance(self.norm, (colors.NoNorm, colors.BoundaryNorm)):
754768
b = self._boundaries
755769
xn = x
756-
xout = x
757770
else:
758771
# Do calculations using normalized coordinates so
759772
# as to make the interpolation more accurate.
760773
b = self.norm(self._boundaries, clip=False).filled()
761-
# We do our own clipping so that we can allow a tiny
762-
# bit of slop in the end point ticks to allow for
763-
# floating point errors.
764774
xn = self.norm(x, clip=False).filled()
765-
in_cond = (xn > -0.001) & (xn < 1.001)
766-
xn = np.compress(in_cond, xn)
767-
xout = np.compress(in_cond, x)
768-
# The rest is linear interpolation with clipping.
775+
# The rest is linear interpolation with extrapolation at ends.
769776
y = self._y
770777
N = len(b)
771-
ii = np.minimum(np.searchsorted(b, xn), N-1)
772-
i0 = np.maximum(ii - 1, 0)
778+
ii = np.searchsorted(b, xn)
779+
i0 = ii - 1
780+
itop = (ii == N)
781+
ibot = (ii == 0)
782+
i0[itop] -= 1
783+
ii[itop] -= 1
784+
i0[ibot] += 1
785+
ii[ibot] += 1
786+
773787
#db = b[ii] - b[i0]
774788
db = np.take(b, ii) - np.take(b, i0)
775-
db = np.where(i0==ii, 1.0, db)
776789
#dy = y[ii] - y[i0]
777790
dy = np.take(y, ii) - np.take(y, i0)
778791
z = np.take(y, i0) + (xn-np.take(b,i0))*dy/db
779-
return xout, z
792+
793+
return z
780794

781795
def set_alpha(self, alpha):
782796
self.alpha = alpha
@@ -834,10 +848,13 @@ def on_mappable_changed(self, mappable):
834848
self.set_clim(mappable.get_clim())
835849
self.update_normal(mappable)
836850

837-
def add_lines(self, CS):
851+
def add_lines(self, CS, erase=True):
838852
'''
839853
Add the lines from a non-filled
840854
:class:`~matplotlib.contour.ContourSet` to the colorbar.
855+
856+
Set *erase* to False if these lines should be added to
857+
any pre-existing lines.
841858
'''
842859
if not isinstance(CS, contour.ContourSet) or CS.filled:
843860
raise ValueError('add_lines is only for a ContourSet of lines')
@@ -851,7 +868,8 @@ def add_lines(self, CS):
851868
#tcolors = [col.get_colors()[0] for col in CS.collections]
852869
#tlinewidths = [col.get_linewidth()[0] for lw in CS.collections]
853870
#print 'tlinewidths:', tlinewidths
854-
ColorbarBase.add_lines(self, CS.levels, tcolors, tlinewidths)
871+
ColorbarBase.add_lines(self, CS.levels, tcolors, tlinewidths,
872+
erase=erase)
855873

856874
def update_normal(self, mappable):
857875
'''
@@ -884,7 +902,7 @@ def update_bruteforce(self, mappable):
884902
self.outline = None
885903
self.patch = None
886904
self.solids = None
887-
self.lines = None
905+
self.lines = list()
888906
self.dividers = None
889907
self.set_alpha(mappable.get_alpha())
890908
self.cmap = mappable.cmap

‎lib/matplotlib/colors.py

Copy file name to clipboardExpand all lines: lib/matplotlib/colors.py
+3-4Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,11 +510,10 @@ def __call__(self, X, alpha=None, bytes=False):
510510
xa = np.array([X])
511511
else:
512512
vtype = 'array'
513-
xma = ma.array(X, copy=False)
514-
mask_bad = xma.mask
515-
xa = xma.data.copy() # Copy here to avoid side effects.
513+
xma = ma.array(X, copy=True) # Copy here to avoid side effects.
514+
mask_bad = xma.mask # Mask will be used below.
515+
xa = xma.filled() # Fill to avoid infs, etc.
516516
del xma
517-
# masked values are substituted below; no need to fill them here
518517

519518
if xa.dtype.char in np.typecodes['Float']:
520519
# Treat 1.0 as slightly less than 1.

0 commit comments

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