-
Notifications
You must be signed in to change notification settings - Fork 0
/
warpcmap.py
155 lines (122 loc) · 5.13 KB
/
warpcmap.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import numpy as np
from scipy.special import betainc
from matplotlib import cm, rcParams
from matplotlib.colors import ListedColormap
from matplotlib.pyplot import gca
from scipy.optimize import root_scalar
def warp_colormap(basemap, z, beta=1, Nentries=256):
"""
Construct a new colormap by warping basemap so that the colour
in "middle" of the basemap is (ie, corresponding to a value of 0.5)
corresponds to the value z and the rate of change of colours around z
is given by beta.
Parameters
----------
basemap: Matplotlib ColorMap or string naming one.
The colormap to warp
z: float (0 < z < 1)
The location that the middle of the basemap is warped to.
For instance, if the basemap is the 'jet' colourmap, so that
the middle of the map is green, then in the new colourmap,
green corresponds to the value z.
beta: float (beta > 0)
Beta controls the rate of change of colours close to z. It is
approximately the gradient of the mapping between the new colours
and the old colours. Values of beta in the range 1 to 5 are usual
as they give more resolution to the data values close to z.
beta < 1 compresses the colours close to z.
Nentries: int
Number of entries in the new colourmap.
Returns
-------
newmap: ListedColormap
The warped colourmap.
Example
-------
Emphasise the data values around 0.8
>>> cmap = warp_colormap('jet', z=0.8, beta=3)
>>> imshow(X, cmap=cmap)
>>> colorbar()
Note
----
If the range of the data is not [0, 1], then z is linearly mapped
to the data range so if the data range is (100, 120) and z = 0.8,
then the emphasised values will be around 116.
"""
if isinstance(basemap, str):
basemap = cm.get_cmap(basemap)
def objective(alpha):
return betainc(alpha, beta, z) - 0.5
soln = root_scalar(objective, bracket=(1e-10, 1e2))
alpha = soln.root
rgba = np.zeros((Nentries, 4))
for n, y in enumerate(np.linspace(0, 1, Nentries)):
x = betainc(alpha, beta, y)
rgba[n,:] = basemap(x)
newmap = ListedColormap(rgba)
return newmap
def wimshow(X,
cmap=None,
vmin=None, vmax=None, vmid=None, beta=1, Nentries=256,
ax=None,
**kwargs):
"""
Convenience wrapper for `imshow` for displaying scalar data that allows
setting of the range of the data values that the coloramp covers and
how it is warped.
Parameters
----------
X : array-like
The image with scalar data. The data is visualized
using a colormap. If RGB or RGBA data is to be displayed, just
use `imshow` directly.
The two dimensions (M, N) define the rows and columns of
the image.
cmap : str or `~matplotlib.colors.Colormap`, optional
The Colormap instance or registered colormap name used to map
scalar data to colors.
Defaults to :rc:`image.cmap`.
vmin, vmax : scalar, optional
When using scalar data and no explicit *norm*, *vmin* and *vmax*
define the data range that the colormap covers. By default,
the colormap covers the complete value range of the supplied
data. *vmin*, *vmax* are ignored if the *norm* parameter is used.
vmid: scalar, optional
The data value that the middle of the colormap is warped to.
For instance, if the colormap is the 'jet' colourmap, so that
the middle of the map is green, then in the new colourmap,
green corresponds to the value vmid.
Default is the middle of the range of the data.
beta: scalar > 0, optional
Beta controls the rate of change of colours close to *vmid*.
Larger values of beta give a more rapid change of colour with
data value. Values of beta in the range 1 to 5 are usual
as they give more resolution to the data values close to *vmid*.
beta < 1 compresses the colours close to *vmid*.
Nentries: int, optional
Number of entries in the warped colourmap.
Default: 256
ax: matplotlib.axes.Axes, optional
The Matplotlib axes in which to plot.
Default: The current axes.
Returns
-------
image : `~matplotlib.image.AxesImage`
Other Parameters
----------------
All other parameters are passed directly to `imshow`.
"""
assert len(X.shape) == 2, "wimshow only supports scalar data; use imshow for RGB and RGBA data"
if cmap is None:
cmap = rcParams['image.cmap']
if vmin is None:
vmin = X.min()
if vmax is None:
vmax = X.max()
if vmid is None:
vmid = (vmin + vmax)/2
if ax is None:
ax = gca()
z = (vmid - vmin)/(vmax-vmin)
warped = warp_colormap(cmap, z, beta=1, Nentries=Nentries)
return ax.imshow(X, cmap=warped, vmin=vmin, vmax=vmax, **kwargs)