Skip to content

Commit

Permalink
Improvements and docs for QuadMesh
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Nov 30, 2017
1 parent f45d1d8 commit 2899a88
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 14 deletions.
34 changes: 34 additions & 0 deletions examples/reference/elements/bokeh/QuadMesh.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,40 @@
"source": [
"Now when you hover over this visualization, you can see the sample value as well as an outline of the selected bin."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Irregular meshes\n",
"\n",
"In addition to axis aligned meshes like those we worked with above, a ``QuadMesh`` may also be used to represent irregular meshes. In this example we will create an irregular mesh consisting of 2D X, Y and Z arrays defining the position and value of each simplex in the mesh:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"n=20\n",
"coords = np.linspace(-1.5,1.5,n)\n",
"X,Y = np.meshgrid(coords, coords);\n",
"Qx = np.cos(Y) - np.cos(X)\n",
"Qz = np.sin(Y) + np.sin(X)\n",
"Z = np.sqrt(X**2 + Y**2)\n",
"\n",
"print(Qx.shape, Qz.shape, Z.shape)\n",
"qmesh = hv.QuadMesh((Qx, Qz, Z))\n",
"qmesh"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Unlike regular meshes an irregularly sampled mesh cannot be selected or grouped by value."
]
}
],
"metadata": {
Expand Down
34 changes: 34 additions & 0 deletions examples/reference/elements/matplotlib/QuadMesh.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,40 @@
"source": [
"To use an interactive hover tool to inspect the sample values, you can use ``QuadMesh`` with the hover tool in the [Bokeh backend](../bokeh/QuadMesh.ipynb)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Irregular meshes\n",
"\n",
"In addition to axis aligned meshes like those we worked with above, a ``QuadMesh`` may also be used to represent irregular meshes. In this example we will create an irregular mesh consisting of 2D X, Y and Z arrays defining the position and value of each simplex in the mesh:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"n=20\n",
"coords = np.linspace(-1.5,1.5,n)\n",
"X,Y = np.meshgrid(coords, coords);\n",
"Qx = np.cos(Y) - np.cos(X)\n",
"Qz = np.sin(Y) + np.sin(X)\n",
"Z = np.sqrt(X**2 + Y**2)\n",
"\n",
"print(Qx.shape, Qz.shape, Z.shape)\n",
"qmesh = hv.QuadMesh((Qx, Qz, Z))\n",
"qmesh + qmesh.opts(style=dict(shading='gouraud'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Unlike regular meshes an irregularly sampled mesh cannot be selected or grouped by value."
]
}
],
"metadata": {
Expand Down
10 changes: 6 additions & 4 deletions holoviews/core/data/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def coords(cls, dataset, dim, ordered=False, expanded=False, edges=False):
data = dataset.data[dim.name]
else:
data = util.expand_grid_coords(dataset, dim)
if edges:
if edges and data.shape == dataset.data[dataset.vdims[0].name].shape:
data = cls._infer_interval_breaks(data, axis=1)
data = cls._infer_interval_breaks(data, axis=0)
return data
Expand All @@ -186,7 +186,7 @@ def coords(cls, dataset, dim, ordered=False, expanded=False, edges=False):
isedges = (dim in dataset.kdims and len(shape) == dataset.ndims
and len(data) == (shape[dataset.ndims-idx-1]+1))
if edges and not isedges:
data = util.compute_edges(data)
data = cls._infer_interval_breaks(data)
elif not edges and isedges:
data = np.convolve(data, [0.5, 0.5], 'valid')
return data
Expand Down Expand Up @@ -273,10 +273,12 @@ def ndloc(cls, dataset, indices):
selected[kd.name] = coords
all_scalar = False
for d in dataset.dimensions():
arr = dataset.dimension_values(vd, flat=False)
if d in dataset.kdims and cls.irregular(dataset, d):
continue
arr = dataset.dimension_values(d, flat=False)
if all_scalar and len(dataset.vdims) == 1:
return arr[tuple(ind[0] for ind in adjusted_inds)]
selected[vd.name] = arr[tuple(adjusted_inds)]
selected[d.name] = arr[tuple(adjusted_inds)]
return tuple(selected[d.name] for d in dataset.dimensions())


Expand Down
4 changes: 4 additions & 0 deletions holoviews/core/data/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ def init(cls, eltype, data, kdims, vdims):

return data, {'kdims':kdims, 'vdims':vdims}, kwargs

@classmethod
def irregular(cls, dataset, dim):
"ImageInterface does not support irregular data"
return False

@classmethod
def shape(cls, dataset, gridded=False):
Expand Down
21 changes: 11 additions & 10 deletions holoviews/plotting/mpl/raster.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,38 +234,39 @@ def get_data(self, element, ranges, style):
zdata = element.dimension_values(2, flat=False)
data = np.ma.array(zdata, mask=np.logical_not(np.isfinite(zdata)))
expanded = element.interface.irregular(element, element.kdims[0])
coords = [element.interface.coords(element, d, expanded=expanded, edges=True)
edges = style.get('shading') != 'gouraud'
coords = [element.interface.coords(element, d, expanded=expanded, edges=edges)
for d in element.kdims]
if self.invert_axes:
coords = coords[::-1]
data = data.T
cmesh_data = coords + [data]
style['locs'] = np.concatenate(coords)
if expanded:
style['locs'] = np.concatenate(coords)
vdim = element.vdims[0]
self._norm_kwargs(element, ranges, style, vdim)
return tuple(cmesh_data), style, {}


def init_artists(self, ax, plot_args, plot_kwargs):
locs = plot_kwargs.pop('locs')
locs = plot_kwargs.pop('locs', None)
artist = ax.pcolormesh(*plot_args, **plot_kwargs)
return {'artist': artist, 'locs': locs}


def update_handles(self, key, axis, element, ranges, style):
cmesh = self.handles['artist']
locs = np.concatenate(element.data[:2])

if (locs != self.handles['locs']).any():
return super(QuadMeshPlot, self).update_handles(key, axis, element,
ranges, style)
else:
data, style, axis_kwargs = self.get_data(element, ranges, style)
data, style, axis_kwargs = self.get_data(element, ranges, style)
locs = style.get('locs')
old_locs = self.handles.get('locs')
if None in (locs, old_locs) or (locs == old_locs).all():
cmesh.set_array(data[-1])
cmesh.set_clim((style['vmin'], style['vmax']))
if 'norm' in style:
cmesh.norm = style['norm']
return axis_kwargs
return super(QuadMeshPlot, self).update_handles(key, axis, element,
ranges, style)


class RasterGridPlot(GridPlot, OverlayPlot):
Expand Down

0 comments on commit 2899a88

Please sign in to comment.