diff --git a/.travis.yml b/.travis.yml index c456341474..1919dee0dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,6 +66,8 @@ before-script: - "echo 'backend : Agg' > $HOME/.matplotlib/matplotlibrc" script: + - export HOLOVIEWSRC=`pwd`'/holoviews.rc' + - echo 'import holoviews as hv;hv.config(style_17=True)' > holoviews.rc - nosetests --with-doctest --with-coverage --cover-package=holoviews - cd doc/nbpublisher; chmod +x test_notebooks.py; BOKEH_DEV=True ./test_notebooks.py - chmod +x concat_html.py; ./concat_html.py ../test_data ../test_html diff --git a/holoviews/__init__.py b/holoviews/__init__.py index 2c2d4017f9..faa8ab920e 100644 --- a/holoviews/__init__.py +++ b/holoviews/__init__.py @@ -11,7 +11,7 @@ __version__ = param.Version(release=(1,7,0), fpath=__file__, commit="$Format:%h$", reponame='holoviews') -from .core import archive # noqa (API import) +from .core import archive, config # noqa (API import) from .core.dimension import OrderedDict, Dimension # noqa (API import) from .core.boundingregion import BoundingBox # noqa (API import) from .core.options import (Options, Store, Cycle, # noqa (API import) diff --git a/holoviews/core/dimension.py b/holoviews/core/dimension.py index 18b54a67e1..8746ac16b2 100644 --- a/holoviews/core/dimension.py +++ b/holoviews/core/dimension.py @@ -15,7 +15,7 @@ group_sanitizer, label_sanitizer, max_range, find_range, dimension_sanitizer, OrderedDict, bytes_to_unicode, unicode, dt64_to_dt, unique_array, - builtins) + builtins, config) from .options import Store, StoreOptions from .pprint import PrettyPrinter @@ -1087,6 +1087,9 @@ def __unicode__(self): def __call__(self, options=None, **kwargs): + if config.warn_options_call: + self.warning('Use of __call__ to set options will be deprecated ' + 'in future. Use the equivalent opts method instead.') return self.opts(options, **kwargs) def opts(self, options=None, **kwargs): diff --git a/holoviews/core/util.py b/holoviews/core/util.py index 1b95a159de..14ea8f41c7 100644 --- a/holoviews/core/util.py +++ b/holoviews/core/util.py @@ -42,6 +42,28 @@ +class Config(param.ParameterizedFunction): + """ + Set of boolean configuration values to change HoloViews' global + behavior. Typically used to control warnings relating to + deprecations or set global parameter such as style 'themes'. + """ + + style_17 = param.Boolean(default=False, doc=""" + Switch to the default style options used up to (and including) + the HoloViews 1.7 release.""") + + warn_options_call = param.Boolean(default=False, doc=""" + Whether to warn when the deprecated __call__ options syntax is + used (the opts method should now be used instead). It is + recommended that users switch this on to update any uses of + __call__ as it will be deprecated in future.""") + + def __call__(self, **params): + self.set_param(**params) + return self + +config = Config() class HashableJSON(json.JSONEncoder): """ diff --git a/holoviews/ipython/__init__.py b/holoviews/ipython/__init__.py index 4e3d0dabc6..642a26dbcd 100644 --- a/holoviews/ipython/__init__.py +++ b/holoviews/ipython/__init__.py @@ -125,7 +125,7 @@ def __call__(self, *args, **params): svg_exporter = Store.renderers['matplotlib'].instance(holomap=None,fig='svg') holoviews.archive.exporters = [svg_exporter] + holoviews.archive.exporters - p = param.ParamOverrides(self, params) + p = param.ParamOverrides(self, {k:v for k,v in params.items() if k!='config'}) resources = self._get_resources(args, params) Store.display_formats = p.display_formats diff --git a/holoviews/plotting/bokeh/__init__.py b/holoviews/plotting/bokeh/__init__.py index 9e082a31f6..cc902401d2 100644 --- a/holoviews/plotting/bokeh/__init__.py +++ b/holoviews/plotting/bokeh/__init__.py @@ -3,7 +3,7 @@ import numpy as np from ...core import (Store, Overlay, NdOverlay, Layout, AdjointLayout, - GridSpace, GridMatrix, NdLayout) + GridSpace, GridMatrix, NdLayout, config) from ...element import (Curve, Points, Scatter, Image, Raster, Path, RGB, Histogram, Spread, HeatMap, Contours, Bars, Box, Bounds, Ellipse, Polygons, BoxWhisker, @@ -19,14 +19,13 @@ from .annotation import TextPlot, LineAnnotationPlot, SplinePlot from .bkcharts import BoxPlot from .callbacks import Callback # noqa (API import) -from .element import OverlayPlot +from .element import OverlayPlot, ElementPlot from .chart import (PointPlot, CurvePlot, SpreadPlot, ErrorPlot, HistogramPlot, SideHistogramPlot, BarPlot, SpikesPlot, SideSpikesPlot, AreaPlot, VectorFieldPlot) from .path import PathPlot, PolygonPlot, ContourPlot from .plot import GridPlot, LayoutPlot, AdjointLayoutPlot -from .raster import (RasterPlot, RGBPlot, HeatmapPlot, - HSVPlot, QuadMeshPlot) +from .raster import RasterPlot, RGBPlot, HeatmapPlot, HSVPlot, QuadMeshPlot from .renderer import BokehRenderer from .tabular import TablePlot from .util import bokeh_version @@ -86,8 +85,11 @@ if DFrame is not None: associations[DFrame] = TablePlot -Store.register(associations, - 'bokeh') +Store.register(associations, 'bokeh') + +if config.style_17: + ElementPlot.show_grid = True + RasterPlot.show_grid = True AdjointLayoutPlot.registry[Histogram] = SideHistogramPlot @@ -104,12 +106,13 @@ Cycle.default_cycles['default_colors'] = ['#30a2da', '#fc4f30', '#e5ae38', '#6d904f', '#8b8b8b'] +dflt_cmap = 'hot' if config.style_17 else 'fire' options = Store.options(backend='bokeh') # Charts options.Curve = Options('style', color=Cycle(), line_width=2) -options.Scatter = Options('style', color=Cycle(), size=point_size, cmap='hot') -options.Points = Options('style', color=Cycle(), size=point_size, cmap='hot') +options.Scatter = Options('style', color=Cycle(), size=point_size, cmap=dflt_cmap) +options.Points = Options('style', color=Cycle(), size=point_size, cmap=dflt_cmap) options.Histogram = Options('style', line_color='black', fill_color=Cycle()) options.ErrorBars = Options('style', color='black') options.Spread = Options('style', color=Cycle(), alpha=0.6, line_color='black') @@ -121,6 +124,8 @@ # Paths options.Contours = Options('style', color=Cycle()) +if not config.style_17: + options.Contours = Options('plot', show_legend=True) options.Path = Options('style', color=Cycle()) options.Box = Options('style', color='black') options.Bounds = Options('style', color='black') @@ -128,10 +133,10 @@ options.Polygons = Options('style', color=Cycle(), line_color='black') # Rasters -options.Image = Options('style', cmap='hot') -options.GridImage = Options('style', cmap='hot') -options.Raster = Options('style', cmap='hot') -options.QuadMesh = Options('style', cmap='hot', line_alpha=0) +options.Image = Options('style', cmap=dflt_cmap) +options.GridImage = Options('style', cmap=dflt_cmap) +options.Raster = Options('style', cmap=dflt_cmap) +options.QuadMesh = Options('style', cmap=dflt_cmap, line_alpha=0) options.HeatMap = Options('style', cmap='RdYlBu_r', line_alpha=0) # Annotations diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py index dbb9e8aea1..9a3b4e7ade 100644 --- a/holoviews/plotting/bokeh/element.py +++ b/holoviews/plotting/bokeh/element.py @@ -102,7 +102,7 @@ class ElementPlot(BokehPlot, GenericElementPlot): show_frame = param.Boolean(default=True, doc=""" Whether or not to show a complete frame around the plot.""") - show_grid = param.Boolean(default=True, doc=""" + show_grid = param.Boolean(default=False, doc=""" Whether to show a Cartesian grid on the plot.""") show_legend = param.Boolean(default=True, doc=""" diff --git a/holoviews/plotting/bokeh/raster.py b/holoviews/plotting/bokeh/raster.py index 48470198b5..b354fd05f0 100644 --- a/holoviews/plotting/bokeh/raster.py +++ b/holoviews/plotting/bokeh/raster.py @@ -10,9 +10,6 @@ class RasterPlot(ColorbarPlot): - show_grid = param.Boolean(default=True, doc=""" - Whether to show a Cartesian grid on the plot.""") - show_legend = param.Boolean(default=False, doc=""" Whether to show legend for the plot.""") diff --git a/holoviews/plotting/mpl/__init__.py b/holoviews/plotting/mpl/__init__.py index e99df4ea8b..4b4b52351f 100644 --- a/holoviews/plotting/mpl/__init__.py +++ b/holoviews/plotting/mpl/__init__.py @@ -3,7 +3,7 @@ from matplotlib import rc_params_from_file -from ...core import Layout, Collator, GridMatrix +from ...core import Layout, Collator, GridMatrix, config from ...core.options import Cycle, Palette, Options from ...core.overlay import NdOverlay, Overlay from ...element import * # noqa (API import) @@ -46,14 +46,6 @@ def set_style(key): plt.rcParams.update(new_style) -styles = {'default': './default.mplstyle', - 'default>1.5': './default1.5.mplstyle'} - -if mpl_ge_150: - set_style('default>1.5') -else: - set_style('default') - # Define matplotlib based style cycles and Palettes def get_color_cycle(): if mpl_ge_150: @@ -67,7 +59,20 @@ def get_color_cycle(): pass # just return axes.color style below return mpl.rcParams['axes.color_cycle'] -Cycle.default_cycles.update({'default_colors': get_color_cycle()}) + +styles = {'default': './default.mplstyle', + 'default>1.5': './default1.5.mplstyle'} + +if config.style_17: + if mpl_ge_150: + set_style('default>1.5') + else: + set_style('default') + Cycle.default_cycles.update({'default_colors': get_color_cycle()}) +else: + Cycle.default_cycles['default_colors'] = ['#30a2da', '#fc4f30', '#e5ae38', + '#6d904f', '#8b8b8b'] + # Filter spectral colormaps to avoid warning in mpl 2.0 Palette.colormaps.update({cm: plt.get_cmap(cm) for cm in plt.cm.datad @@ -160,19 +165,25 @@ def grid_selector(grid): Spikes: SideSpikesPlot, BoxWhisker: SideBoxPlot}) -options = Store.options(backend='matplotlib') +if config.style_17: + CurvePlot.show_grid = True + SideHistogramPlot.show_grid = True + PointPlot.show_grid = True + +options = Store.options(backend='matplotlib') +dflt_cmap = 'hot' if config.style_17 else 'fire' # Default option definitions # Note: *No*short aliases here! e.g use 'facecolor' instead of 'fc' # Charts options.Curve = Options('style', color=Cycle(), linewidth=2) -options.Scatter = Options('style', color=Cycle(), marker='o', cmap='hot') +options.Scatter = Options('style', color=Cycle(), marker='o', cmap=dflt_cmap) options.ErrorBars = Options('style', ecolor='k') options.Spread = Options('style', facecolor=Cycle(), alpha=0.6, edgecolor='k', linewidth=0.5) options.Bars = Options('style', ec='k', color=Cycle()) options.Histogram = Options('style', ec='k', facecolor=Cycle()) -options.Points = Options('style', color=Cycle(), marker='o', cmap='hot') +options.Points = Options('style', color=Cycle(), marker='o', cmap=dflt_cmap) options.Scatter3D = Options('style', c=Cycle(), marker='o') options.Scatter3D = Options('plot', fig_size=150) options.Surface = Options('plot', fig_size=150) @@ -182,10 +193,10 @@ def grid_selector(grid): whiskerprops=dict(color='k', linewidth=1.5)) # Rasters -options.Image = Options('style', cmap='hot', interpolation='nearest') -options.GridImage = Options('style', cmap='hot', interpolation='nearest') -options.Raster = Options('style', cmap='hot', interpolation='nearest') -options.QuadMesh = Options('style', cmap='hot') +options.Image = Options('style', cmap=dflt_cmap, interpolation='nearest') +options.GridImage = Options('style', cmap=dflt_cmap, interpolation='nearest') +options.Raster = Options('style', cmap=dflt_cmap, interpolation='nearest') +options.QuadMesh = Options('style', cmap=dflt_cmap) options.HeatMap = Options('style', cmap='RdYlBu_r', interpolation='nearest') options.HeatMap = Options('plot', show_values=True, xticks=20, yticks=20) options.RGB = Options('style', interpolation='nearest') @@ -197,16 +208,28 @@ def grid_selector(grid): # Annotations options.VLine = Options('style', color=Cycle()) options.HLine = Options('style', color=Cycle()) -options.Spline = Options('style', linewidth=2, edgecolor='r') +if config.style_17: + options.Spline = Options('style', linewidth=2, edgecolor='r') +else: + options.Spline = Options('style', edgecolor=Cycle()) + options.Text = Options('style', fontsize=13) options.Arrow = Options('style', color='k', linewidth=2, fontsize=13) # Paths options.Contours = Options('style', color=Cycle()) options.Contours = Options('plot', show_legend=True) options.Path = Options('style', color=Cycle()) -options.Box = Options('style', color=Cycle()) -options.Bounds = Options('style', color=Cycle()) -options.Ellipse = Options('style', color=Cycle()) + +if config.style_17: + options.Box = Options('style', color=Cycle()) + options.Bounds = Options('style', color=Cycle()) + options.Ellipse = Options('style', color=Cycle()) +else: + options.Box = Options('style', color='black') + options.Bounds = Options('style', color='black') + options.Ellipse = Options('style', color='black') + options.Polygons = Options('style', facecolor=Cycle(), edgecolor='black') + # Interface options.TimeSeries = Options('style', color=Cycle()) diff --git a/holoviews/plotting/mpl/chart.py b/holoviews/plotting/mpl/chart.py index 8946ec7487..e1634fa1e2 100644 --- a/holoviews/plotting/mpl/chart.py +++ b/holoviews/plotting/mpl/chart.py @@ -60,7 +60,7 @@ class CurvePlot(ChartPlot): show_frame = param.Boolean(default=False, doc=""" Disabled by default for clarity.""") - show_grid = param.Boolean(default=True, doc=""" + show_grid = param.Boolean(default=False, doc=""" Enable axis grid.""") show_legend = param.Boolean(default=True, doc=""" @@ -391,7 +391,7 @@ class SideHistogramPlot(AdjoinedPlot, HistogramPlot): offset = param.Number(default=0.2, bounds=(0,1), doc=""" Histogram value offset for a colorbar.""") - show_grid = param.Boolean(default=True, doc=""" + show_grid = param.Boolean(default=False, doc=""" Whether to overlay a grid on the axis.""") def _process_hist(self, hist): @@ -495,7 +495,7 @@ class PointPlot(ChartPlot, ColorbarPlot): Scaling factor which is applied to either the width or area of each point, depending on the value of `scaling_method`.""") - show_grid = param.Boolean(default=True, doc=""" + show_grid = param.Boolean(default=False, doc=""" Whether to draw grid lines at the tick positions.""") size_fn = param.Callable(default=np.abs, doc=""" diff --git a/holoviews/util/__init__.py b/holoviews/util/__init__.py index ae616a4523..c92ef73d93 100644 --- a/holoviews/util/__init__.py +++ b/holoviews/util/__init__.py @@ -186,6 +186,8 @@ class extension(param.ParameterizedFunction): def __call__(self, *args, **params): # Get requested backends + config = params.pop('config', {}) + util.config.set_param(**config) imports = [(arg, self._backends[arg]) for arg in args if arg in self._backends] for p, val in sorted(params.items()):