Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Project: topocm
Views: 391
1
import param
2
3
from holoviews.core.util import *
4
from holoviews.plotting.mpl.chart3d import *
5
from holoviews.plotting.mpl.element import *
6
7
def patch_core_util():
8
import holoviews.core.util
9
10
11
def max_extents(extents, zrange=False):
12
"""
13
Computes the maximal extent in 2D and 3D space from
14
list of 4-tuples or 6-tuples. If zrange is enabled
15
all extents are converted to 6-tuples to comput
16
x-, y- and z-limits.
17
"""
18
if zrange:
19
num = 6
20
inds = [(0, 3), (1, 4), (2, 5)]
21
extents = [e if len(e) == 6 else (e[0], e[1], None,
22
e[2], e[3], None)
23
for e in extents]
24
else:
25
num = 4
26
inds = [(0, 2), (1, 3)]
27
arr = list(zip(*extents)) if extents else []
28
extents = [np.NaN] * num
29
if len(arr) == 0:
30
return extents
31
with warnings.catch_warnings():
32
warnings.filterwarnings('ignore', r'All-NaN (slice|axis) encountered')
33
for lidx, uidx in inds:
34
lower = [v for v in arr[lidx] if v is not None]
35
upper = [v for v in arr[uidx] if v is not None]
36
if lower and isinstance(lower[0], np.datetime64):
37
extents[lidx] = np.min(lower)
38
elif lower:
39
extents[lidx] = np.nanmin(lower)
40
if upper and isinstance(upper[0], np.datetime64):
41
extents[uidx] = np.max(upper)
42
elif upper:
43
extents[uidx] = np.nanmax(upper)
44
return tuple(extents)
45
46
holoviews.core.util.max_extents = max_extents
47
48
49
def patch_plotting_util():
50
import numpy as np
51
def map_colors(arr, crange, cmap, hex=True):
52
"""
53
Maps an array of values to RGB hex strings, given
54
a color range and colormap.
55
"""
56
if crange:
57
cmin, cmax = crange
58
else:
59
cmin, cmax = np.nanmin(arr), np.nanmax(arr)
60
arr = (arr - cmin) / (cmax-cmin)
61
arr = np.ma.array(arr, mask=np.logical_not(np.isfinite(arr)))
62
arr = cmap(arr)
63
if hex:
64
arr *= 255
65
return ["#{0:02x}{1:02x}{2:02x}".format(*(int(v) for v in c[:-1]))
66
for c in arr]
67
else:
68
return arr
69
70
import holoviews.plotting.util
71
holoviews.plotting.util.map_colors = map_colors
72
73
74
def patch_mpl_chart3d():
75
import holoviews.plotting.mpl.chart3d
76
77
import matplotlib.cm as cm
78
from holoviews.plotting.util import map_colors
79
80
holoviews.plotting.mpl.chart3d.cm = cm
81
holoviews.plotting.mpl.chart3d.map_colors = map_colors
82
83
def _finalize_axis(self, key, **kwargs):
84
"""
85
Extends the ElementPlot _finalize_axis method to set appropriate
86
labels, and axes options for 3D Plots.
87
"""
88
axis = self.handles['axis']
89
self.handles['fig'].set_frameon(False)
90
axis.grid(self.show_grid)
91
axis.view_init(elev=self.elevation, azim=self.azimuth)
92
axis.dist = self.distance
93
94
if self.xaxis is None:
95
axis.w_xaxis.line.set_lw(0.)
96
axis.w_xaxis.label.set_text('')
97
if self.yaxis is None:
98
axis.w_yaxis.line.set_lw(0.)
99
axis.w_yaxis.label.set_text('')
100
if self.zaxis is None:
101
axis.w_zaxis.line.set_lw(0.)
102
axis.w_zaxis.label.set_text('')
103
if self.disable_axes:
104
axis.set_axis_off()
105
106
axis.set_axis_bgcolor(self.bgcolor)
107
return super(Plot3D, self)._finalize_axis(key, **kwargs)
108
109
holoviews.plotting.mpl.chart3d.Plot3D._finalize_axis = _finalize_axis
110
111
def update_frame(self, *args, **kwargs):
112
super(Plot3D, self).update_frame(*args, **kwargs)
113
114
holoviews.plotting.mpl.chart3d.Plot3D.update_frame = update_frame
115
116
def initialize_plot(self, ranges=None):
117
axis = self.handles['axis']
118
points = self.hmap.last
119
ranges = self.compute_ranges(self.hmap, self.keys[-1], ranges)
120
ranges = match_spec(points, ranges)
121
key = self.keys[-1]
122
xs, ys, zs = (points.dimension_values(i) for i in range(3))
123
124
style = self.style[self.cyclic_index]
125
cdim = points.get_dimension(self.color_index)
126
if cdim and 'cmap' in style:
127
cs = points.dimension_values(self.color_index)
128
style['c'] = cs
129
if 'clim' not in style:
130
clims = ranges[cdim.name]
131
style.update(vmin=clims[0], vmax=clims[1])
132
if points.get_dimension(self.size_index):
133
style['s'] = self._compute_size(points, style)
134
135
scatterplot = axis.scatter(xs, ys, zs, zorder=self.zorder, **style)
136
137
self.handles['axis'].add_collection(scatterplot)
138
self.handles['artist'] = scatterplot
139
140
return self._finalize_axis(key, ranges=ranges)
141
142
holoviews.plotting.mpl.chart3d.Scatter3DPlot.initialize_plot = initialize_plot
143
144
def update_handles(self, axis, points, key, ranges=None):
145
artist = self.handles['artist']
146
artist._offsets3d = tuple(points[d] for d in points.dimensions())
147
cdim = points.get_dimension(self.color_index)
148
style = self.style[self.cyclic_index]
149
if cdim and 'cmap' in style:
150
cs = points.dimension_values(self.color_index)
151
clim = style['clim'] if 'clim' in style else ranges[cdim.name]
152
cmap = cm.get_cmap(style['cmap'])
153
artist._facecolor3d = map_colors(cs, clim, cmap, False)
154
if points.get_dimension(self.size_index):
155
artist.set_sizes(self._compute_size(points, style))
156
157
holoviews.plotting.mpl.chart3d.Scatter3DPlot.update_handles = update_handles
158
159
def update_handles(self, axis, element, key, ranges=None):
160
if 'artist' in self.handles:
161
self.handles['axis'].collections.remove(self.handles['artist'])
162
mat = element.data
163
rn, cn = mat.shape
164
l, b, zmin, r, t, zmax = self.get_extents(element, ranges)
165
r, c = np.mgrid[l:r:(r-l)/float(rn), b:t:(t-b)/float(cn)]
166
167
style_opts = self.style[self.cyclic_index]
168
169
if self.plot_type == "wireframe":
170
self.handles['artist'] = self.handles['axis'].plot_wireframe(r, c, mat, **style_opts)
171
elif self.plot_type == "surface":
172
style_opts['vmin'] = zmin
173
style_opts['vmax'] = zmax
174
self.handles['artist'] = self.handles['axis'].plot_surface(r, c, mat, **style_opts)
175
elif self.plot_type == "contour":
176
self.handles['artist'] = self.handles['axis'].contour3D(r, c, mat, **style_opts)
177
178
holoviews.plotting.mpl.chart3d.SurfacePlot.update_handles = update_handles
179
180
def update_handles(self, axis, element, key, ranges=None):
181
if 'artist' in self.handles:
182
self.handles['axis'].collections.remove(self.handles['artist'])
183
style_opts = self.style[self.cyclic_index]
184
dims = element.dimensions(label=True)
185
vrange = ranges[dims[2]]
186
x, y, z = [element.dimension_values(d) for d in dims]
187
artist = axis.plot_trisurf(x, y, z, vmax=vrange[1],
188
vmin=vrange[0], **style_opts)
189
self.handles['artist'] = artist
190
191
holoviews.plotting.mpl.chart3d.TrisurfacePlot.update_handles = update_handles
192
193
194
def patch_mpl_element():
195
import holoviews.plotting.mpl.element
196
197
def _finalize_axis(self, key, title=None, ranges=None, xticks=None, yticks=None,
198
zticks=None, xlabel=None, ylabel=None, zlabel=None):
199
"""
200
Applies all the axis settings before the axis or figure is returned.
201
Only plots with zorder 0 get to apply their settings.
202
203
When the number of the frame is supplied as n, this method looks
204
up and computes the appropriate title, axis labels and axis bounds.
205
"""
206
element = self._get_frame(key)
207
self.current_frame = element
208
axis = self.handles['axis']
209
if self.bgcolor:
210
axis.set_axis_bgcolor(self.bgcolor)
211
212
subplots = list(self.subplots.values()) if self.subplots else []
213
if self.zorder == 0 and key is not None:
214
title = None if self.zorder > 0 else self._format_title(key)
215
suppress = any(sp.hmap.type in self._suppressed for sp in [self] + subplots
216
if isinstance(sp.hmap, HoloMap))
217
if element is not None and not suppress:
218
xlabel, ylabel, zlabel = self._axis_labels(element, subplots, xlabel, ylabel, zlabel)
219
if self.invert_axes:
220
xlabel, ylabel = ylabel, xlabel
221
222
self._finalize_limits(axis, element, subplots, ranges)
223
224
# Tick formatting
225
xdim, ydim = element.get_dimension(0), element.get_dimension(1)
226
xformat, yformat = None, None
227
if xdim is None:
228
pass
229
elif xdim.value_format:
230
xformat = xdim.value_format
231
elif xdim.type in xdim.type_formatters:
232
xformat = xdim.type_formatters[xdim.type]
233
if xformat:
234
axis.xaxis.set_major_formatter(wrap_formatter(xformat))
235
236
if ydim is None:
237
pass
238
elif ydim.value_format:
239
yformat = ydim.value_format
240
elif ydim.type in ydim.type_formatters:
241
yformat = ydim.type_formatters[ydim.type]
242
if yformat:
243
axis.yaxis.set_major_formatter(wrap_formatter(yformat))
244
245
if self.zorder == 0 and not subplots:
246
legend = axis.get_legend()
247
if legend: legend.set_visible(self.show_legend)
248
249
axis.get_xaxis().grid(self.show_grid)
250
axis.get_yaxis().grid(self.show_grid)
251
252
if xlabel and self.xaxis: axis.set_xlabel(xlabel, **self._fontsize('xlabel'))
253
if ylabel and self.yaxis: axis.set_ylabel(ylabel, **self._fontsize('ylabel'))
254
if zlabel and self.zaxis: axis.set_zlabel(zlabel, **self._fontsize('ylabel'))
255
256
self._apply_aspect(axis)
257
self._subplot_label(axis)
258
if self.apply_ticks:
259
self._finalize_ticks(axis, element, xticks, yticks, zticks)
260
261
262
if self.show_title and title is not None:
263
if 'title' in self.handles:
264
self.handles['title'].set_text(title)
265
else:
266
self.handles['title'] = axis.set_title(title,
267
**self._fontsize('title'))
268
# Always called to ensure log and inverted axes are applied
269
self._finalize_axes(axis)
270
if not self.overlaid and not self.drawn:
271
self._finalize_artist(key)
272
273
for hook in self.finalize_hooks:
274
try:
275
hook(self, element)
276
except Exception as e:
277
self.warning("Plotting hook %r could not be applied:\n\n %s" % (hook, e))
278
279
return super(ElementPlot, self)._finalize_axis(key)
280
281
holoviews.plotting.mpl.element.ElementPlot._finalize_axis = _finalize_axis
282
283
def update_frame(self, key, ranges=None, element=None):
284
axis = self.handles['axis']
285
if element is None:
286
element = self._get_frame(key)
287
else:
288
self.current_frame = element
289
self.current_key = key
290
291
if isinstance(self.hmap, DynamicMap):
292
range_obj = element
293
items = element.items()
294
else:
295
range_obj = self.hmap
296
items = element.items()
297
ranges = self.compute_ranges(range_obj, key, ranges)
298
299
for k, subplot in self.subplots.items():
300
el = element.get(k, None)
301
if isinstance(self.hmap, DynamicMap):
302
idx = dynamic_update(self, subplot, k, element, items)
303
if idx is not None:
304
_, el = items.pop(idx)
305
subplot.update_frame(key, ranges, el)
306
307
if isinstance(self.hmap, DynamicMap) and items:
308
raise Exception("Some Elements returned by the dynamic callback "
309
"were not initialized correctly and could not be "
310
"rendered.")
311
312
if self.show_legend:
313
self._adjust_legend(element, axis)
314
315
self._finalize_axis(key, ranges=ranges)
316
317
holoviews.plotting.mpl.element.OverlayPlot.update_frame = update_frame
318
319
320
def patch_all():
321
with param.logging_level('error'):
322
patch_core_util()
323
patch_plotting_util()
324
patch_mpl_chart3d()
325
patch_mpl_element()
326
327
328