Skip to content

Commit

Permalink
Merge branch 'master' into dynamic_sampled
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Dec 4, 2015
2 parents f171f9b + 131287d commit d37c3dd
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 16 deletions.
56 changes: 53 additions & 3 deletions doc/Tutorials/Options.ipynb
Expand Up @@ -405,7 +405,7 @@
"\n",
"In this way, it is possible to build complex objects with arbitrary customization, step by step. As mentioned above, it is also possible to customize objects already combined into a complex container, just by specifying an option for a suitable key (e.g. ``'Image.Function.Sine'`` above). This flexible system should allow for any level of customization that is needed.\n",
"\n",
"Finally, there is one more way to apply options that is a mix of the above approaches -- temporarily assign a new ID to the object and apply a set of customizations during a specific portion of the code:"
"Finally, there is one more way to apply options that is a mix of the above approaches -- temporarily assign a new ID to the object and apply a set of customizations during a specific portion of the code. To illustrate this, we'll create a new Image object called 'Cosine':"
]
},
{
Expand All @@ -416,7 +416,57 @@
},
"outputs": [],
"source": [
"with hv.StoreOptions.options(green_sine, options={'Image':{'style':{'cmap':'Reds'}}}):\n",
"cosine = hv.Image(np.cos(x**2+y**2), group=\"Function\", label=\"Cosine\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"with hv.StoreOptions.options(cosine, options={'Image':{'style':{'cmap':'Reds'}}}):\n",
" data, info = renderer(cosine)\n",
"print(info)\n",
"SVG(data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here the result is in red as it was generated in the context of a 'Reds' colormap but if we display cosine again outside the scope of the with statement, it retains the default settings:m"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"cosine"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that if we want to use this context manager to set new options on the existing green_sine object, you must specify that the options apply to a specific Image by stating the applicable group and label:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"with hv.StoreOptions.options(green_sine, options={'Image.Function.Sine':{'style':{'cmap':'Purples'}}}):\n",
" data, info = renderer(green_sine)\n",
"print(info)\n",
"SVG(data)"
Expand All @@ -426,7 +476,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Here the result is red, because it was rendered within the options context above, but were we to render the ``green_sine`` again it would still be green; the options are applied only within the scope of the ``with`` statement."
"Now the result inside the context is purple but elswhere green_sine remains green. If the group and label had not been specified above, the specific customization applied earlier (setting the green colormap) would take precedence over the general settings of Image. For this reason, it is important to know the appropriate precedence of new customizations and you can always specify the object group and label to make sure the new settings override the old ones."
]
},
{
Expand Down
5 changes: 3 additions & 2 deletions holoviews/core/spaces.py
Expand Up @@ -383,8 +383,9 @@ class DynamicMap(HoloMap):

sampled = param.Boolean(default=False, doc="""
Allows defining a DynamicMap in closed mode without defining the
dimension bounds or values. Useful for allowing to let a HoloMap
in a composite plot to define the dimension sampling.
dimension bounds or values. The DynamicMap may then be explicitly
sampled via getitem or the sampling is determined during plotting
by a HoloMap with fixed sampling.
""")

def __init__(self, callback, initial_items=None, **params):
Expand Down
4 changes: 2 additions & 2 deletions holoviews/plotting/bokeh/element.py
Expand Up @@ -262,7 +262,7 @@ def _plot_properties(self, key, plot, element):
if self.show_title:
plot_props['title'] = self._format_title(key, separator=' ')
if self.bgcolor:
plot_props['background_fill'] = self.bgcolor
plot_props['background_fill_color'] = self.bgcolor
if self.border is not None:
plot_props['min_border'] = self.border
lod = dict(self.defaults()['lod'], **self.lod)
Expand Down Expand Up @@ -308,7 +308,7 @@ def _axis_properties(self, axis, key, plot, element):
axis_props['ticker'] = ticker
elif isinstance(ticker, int):
axis_props['ticker'] = BasicTicker(desired_num_ticks=ticker)
elif isinstance(ticker, list):
elif isinstance(ticker, (tuple, list)):
if all(isinstance(t, tuple) for t in ticker):
pass
else:
Expand Down
2 changes: 2 additions & 0 deletions holoviews/plotting/bokeh/renderer.py
Expand Up @@ -59,6 +59,8 @@ def __call__(self, obj, fmt=None):
plotobjects = [h for handles in plot.traverse(lambda x: x.current_handles)
for h in handles]
data = OrderedDict()
if not old_bokeh:
data['root'] = plot.state._id
for plotobj in plotobjects:
if old_bokeh:
json = plotobj.vm_serialize(changed_only=True)
Expand Down
6 changes: 3 additions & 3 deletions holoviews/plotting/mpl/element.py
Expand Up @@ -301,7 +301,7 @@ def _finalize_ticks(self, axis, view, xticks, yticks, zticks):
else:
locator = ticker.MaxNLocator(self.xticks)
axis.xaxis.set_major_locator(locator)
elif isinstance(self.xticks, list):
elif isinstance(self.xticks, (list, tuple)):
if all(isinstance(t, tuple) for t in self.xticks):
xticks, xlabels = zip(*self.xticks)
else:
Expand Down Expand Up @@ -330,7 +330,7 @@ def _finalize_ticks(self, axis, view, xticks, yticks, zticks):
else:
locator = ticker.MaxNLocator(self.yticks)
axis.yaxis.set_major_locator(locator)
elif isinstance(self.yticks, list):
elif isinstance(self.yticks, (list, tuple)):
if all(isinstance(t, tuple) for t in self.yticks):
yticks, ylabels = zip(*self.yticks)
else:
Expand Down Expand Up @@ -361,7 +361,7 @@ def _finalize_ticks(self, axis, view, xticks, yticks, zticks):
else:
locator = ticker.MaxNLocator(self.zticks)
axis.zaxis.set_major_locator(locator)
elif isinstance(self.zticks, list):
elif isinstance(self.zticks, (list, tuple)):
if all(isinstance(t, tuple) for t in self.zticks):
zticks, zlabels = zip(*self.zticks)
else:
Expand Down
14 changes: 10 additions & 4 deletions holoviews/plotting/plot.py
Expand Up @@ -135,7 +135,10 @@ class DimensionedPlot(Plot):
Finer control is available by supplying a dictionary where any
unmentioned keys reverts to the default sizes, e.g:
{'ticks':20, 'title':15, 'ylabel':5, 'xlabel':5}""")
{'ticks':20, 'title':15, 'ylabel':5, 'xlabel':5}
You can set the fontsize of both 'ylabel' and 'xlabel' together
using the 'labels' key.""")

show_title = param.Boolean(default=True, doc="""
Whether to display the plot title.""")
Expand Down Expand Up @@ -257,10 +260,13 @@ def _fontsize(self, key, label='fontsize', common=True):
if not self.fontsize:
return {}
if isinstance(self.fontsize, dict):
if key not in self.fontsize:
return {}
else:
if key in self.fontsize:
return {label:self.fontsize[key]}
elif key in ['ylabel', 'xlabel'] and 'labels' in self.fontsize:
return {label:self.fontsize['labels']}
else:
return {}

return {label:self.fontsize} if common else {}


Expand Down
16 changes: 15 additions & 1 deletion holoviews/plotting/util.py
@@ -1,7 +1,7 @@
import param

from ..core import (HoloMap, DynamicMap, CompositeOverlay, Layout,
GridSpace, NdLayout)
GridSpace, NdLayout, Store)
from ..core.util import match_spec


Expand Down Expand Up @@ -144,3 +144,17 @@ def initialize_sampled(obj, dimensions, key):
selection = obj.select([DynamicMap], **select)
except KeyError:
pass


def save_frames(obj, filename, fmt=None, backend=None, options=None):
"""
Utility to export object to files frame by frame, numbered individually.
Will use default backend and figure format by default.
"""
backend = Store.current_backend if backend is None else backend
renderer = Store.renderers[backend]
fmt = renderer.params('fig').objects[0] if fmt is None else fmt
plot = renderer.get_plot(obj)
for i in range(len(plot)):
plot.update(i)
renderer.save(plot, '%s_%s' % (filename, i), fmt=fmt, options=options)

0 comments on commit d37c3dd

Please sign in to comment.