Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ install:
# Useful for debugging any issues with conda
- conda info -a
- conda create -q -n holoviews python=$TRAVIS_PYTHON_VERSION
- conda env update -n holoviews -q -f environment.yml
- travis_wait conda env update -n holoviews -q -f environment.yml
- source activate holoviews
- python setup.py develop
- conda env export
Expand Down
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ dependencies:
- conda-forge::netcdf4=1.3.1
- conda-forge::ffmpeg
- conda-forge::flexx=0.4.1
- conda-forge::plotly=2.7
- plotly::plotly=3.4
- bokeh::bokeh=1.0.0
- bokeh::selenium
# Testing requirements
Expand Down
4 changes: 2 additions & 2 deletions examples/reference/elements/plotly/Scatter.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"metadata": {},
"outputs": [],
"source": [
"%%opts Scatter (color='k' symbol='s' size=10)\n",
"%%opts Scatter (color='black' symbol='circle' size=10)\n",
"np.random.seed(42)\n",
"coords = [(i, np.random.random()) for i in range(20)]\n",
"hv.Scatter(coords)"
Expand All @@ -56,7 +56,7 @@
"metadata": {},
"outputs": [],
"source": [
"%%opts Scatter (color='k' symbol='x' size=10)\n",
"%%opts Scatter (color='black' symbol='x' size=10)\n",
"hv.Scatter(coords)[0:12] + hv.Scatter(coords)[12:20]"
]
},
Expand Down
2 changes: 1 addition & 1 deletion examples/reference/elements/plotly/Surface.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"metadata": {},
"outputs": [],
"source": [
"%%opts Surface [width=500 height=500] (cmap='plasma')\n",
"%%opts Surface [width=500 height=500] (cmap='viridis')\n",
"hv.Surface(np.sin(np.linspace(0,100*np.pi*2,10000)).reshape(100,100))"
]
},
Expand Down
8 changes: 8 additions & 0 deletions holoviews/plotting/plotly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
from .raster import * # noqa (API import)
from .plot import * # noqa (API import)
from .tabular import * # noqa (API import)
from ...core.util import LooseVersion, VersionError
import plotly

if LooseVersion(plotly.__version__) < '3.4.0':
raise VersionError(
"The plotly extension requires a plotly version >=3.4.0, "
"please upgrade from plotly %s to a more recent version."
% plotly.__version__, plotly.__version__, '3.4.0')

Store.renderers['plotly'] = PlotlyRenderer.instance()

Expand Down
5 changes: 2 additions & 3 deletions holoviews/plotting/plotly/chart3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from matplotlib.cm import get_cmap
from plotly import colors
from plotly.tools import FigureFactory as FF
from plotly.graph_objs import Scene, XAxis, YAxis, ZAxis

try:
from plotly.figure_factory._trisurf import trisurf as trisurface
Expand Down Expand Up @@ -50,8 +49,8 @@ def init_layout(self, key, element, ranges):
else:
opts['aspectmode'] = 'manual'
opts['aspectratio'] = self.aspect
scene = Scene(xaxis=XAxis(xaxis), yaxis=YAxis(yaxis),
zaxis=ZAxis(zaxis), **opts)
scene = go.layout.Scene(xaxis=xaxis, yaxis=yaxis,
zaxis=zaxis, **opts)

return dict(width=self.width, height=self.height,
title=self._format_title(key, separator=' '),
Expand Down
4 changes: 2 additions & 2 deletions holoviews/plotting/plotly/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def init_layout(self, key, element, ranges, xdim=None, ydim=None):
options['yaxis'] = yaxis

l, b, r, t = self.margins
margin = go.Margin(l=l, r=r, b=b, t=t, pad=4)
margin = go.layout.Margin(l=l, r=r, b=b, t=t, pad=4)
return go.Layout(width=self.width, height=self.height,
title=self._format_title(key, separator=' '),
plot_bgcolor=self.bgcolor, margin=margin,
Expand Down Expand Up @@ -268,7 +268,7 @@ def generate_plot(self, key, ranges):
if figure is None:
figure = fig
else:
figure['data'].extend(fig['data'])
figure.add_traces(fig.data)

layout = self.init_layout(key, element, ranges)
figure['layout'].update(layout)
Expand Down
5 changes: 3 additions & 2 deletions holoviews/plotting/plotly/plotlywidgets.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ var PlotlyMethods = {
plot.data[i][key] = data.data[i][key];
}
}
Plotly.relayout(plot, data.layout);
Plotly.redraw(plot);
var plotly = window._Plotly || window.Plotly;
plotly.relayout(plot, data.layout);
plotly.redraw(plot);
}
}

Expand Down
15 changes: 8 additions & 7 deletions holoviews/plotting/plotly/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
plot.data[i][key] = obj[key];
}});
}});
Plotly.relayout(plot, data.layout);
Plotly.redraw(plot);
var plotly = window._Plotly || window.Plotly;
plotly.relayout(plot, data.layout);
plotly.redraw(plot);
"""

PLOTLY_WARNING = """
Expand Down Expand Up @@ -70,8 +71,7 @@ def diff(self, plot, serialize=True):
Returns a json diff required to update an existing plot with
the latest plot data.
"""
diff = {'data': plot.state.get('data', []),
'layout': plot.state.get('layout', {})}
diff = plot.state.to_plotly_json()
if serialize:
return json.dumps(diff, cls=utils.PlotlyJSONEncoder)
else:
Expand All @@ -83,8 +83,8 @@ def _figure_data(self, plot, fmt=None, divuuid=None, comm=True, as_script=False,
if divuuid is None:
divuuid = plot.id

jdata = json.dumps(figure.get('data', []), cls=utils.PlotlyJSONEncoder)
jlayout = json.dumps(figure.get('layout', {}), cls=utils.PlotlyJSONEncoder)
jdata = json.dumps(figure.data, cls=utils.PlotlyJSONEncoder)
jlayout = json.dumps(figure.layout, cls=utils.PlotlyJSONEncoder)

config = {}
config['showLink'] = False
Expand All @@ -98,7 +98,8 @@ def _figure_data(self, plot, fmt=None, divuuid=None, comm=True, as_script=False,
'</script>')

script = '\n'.join([
'Plotly.plot("{id}", {data}, {layout}, {config}).then(function() {{',
'var plotly = window._Plotly || window.Plotly;'
'plotly.plot("{id}", {data}, {layout}, {config}).then(function() {{',
' var elem = document.getElementById("{id}.loading"); elem.parentNode.removeChild(elem);',
'}})']).format(id=divuuid,
data=jdata,
Expand Down
13 changes: 5 additions & 8 deletions holoviews/plotting/plotly/util.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
import plotly.graph_objs as go


def add_figure(fig, subfig, r, c, idx):
"""
Combines a figure with an existing figure created with
plotly.tools.make_subplots, by adding the data and merging
axis layout options.
"""
ref = fig._grid_ref[r][c][0][1:]
layout = replace_refs(subfig['layout'], ref)
layout = replace_refs(subfig['layout'].to_plotly_json(), ref)

fig['layout']['xaxis%s'%ref].update(layout.get('xaxis', {}))
fig['layout']['yaxis%s'%ref].update(layout.get('yaxis', {}))
fig['layout']['annotations'].extend(layout.get('annotations', []))
fig['layout']['annotations'] += layout.get('annotations', ())
for d in subfig['data']:
fig.append_trace(d, r+1, c+1)
fig.add_trace(d, row=r+1, col=c+1)


def replace_refs(obj, ind):
"""
Replaces xref and yref to allow combining multiple plots
"""
if isinstance(obj, go.graph_objs.PlotlyList):
if isinstance(obj, tuple):
return [replace_refs(o, ind) for o in obj]
elif isinstance(obj, go.graph_objs.PlotlyDict):
elif isinstance(obj, dict):
new_obj = {}
for k, v in obj.items():
if k in ['xref', 'yref']:
Expand Down
20 changes: 10 additions & 10 deletions holoviews/tests/plotting/plotly/testplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,30 +52,30 @@ def test_curve_state(self):
curve = Curve([1, 2, 3])
state = self._get_plot_state(curve)
self.assertEqual(state['data'][0]['y'], np.array([1, 2, 3]))
self.assertEqual(state['layout']['yaxis']['range'], [1, 3])
self.assertEqual(state['layout']['yaxis']['range'], (1, 3))

def test_scatter3d_state(self):
scatter = Scatter3D(([0,1], [2,3], [4,5]))
state = self._get_plot_state(scatter)
self.assertEqual(state['data'][0]['x'], np.array([0, 1]))
self.assertEqual(state['data'][0]['y'], np.array([2, 3]))
self.assertEqual(state['data'][0]['z'], np.array([4, 5]))
self.assertEqual(state['layout']['scene']['xaxis']['range'], [0, 1])
self.assertEqual(state['layout']['scene']['yaxis']['range'], [2, 3])
self.assertEqual(state['layout']['scene']['zaxis']['range'], [4, 5])
self.assertEqual(state['layout']['scene']['xaxis']['range'], (0, 1))
self.assertEqual(state['layout']['scene']['yaxis']['range'], (2, 3))
self.assertEqual(state['layout']['scene']['zaxis']['range'], (4, 5))

def test_overlay_state(self):
layout = Curve([1, 2, 3]) * Curve([2, 4, 6])
state = self._get_plot_state(layout)
self.assertEqual(state['data'][0]['y'], np.array([1, 2, 3]))
self.assertEqual(state['data'][1]['y'], np.array([2, 4, 6]))
self.assertEqual(state['layout']['yaxis']['range'], [1, 6])
self.assertEqual(state['layout']['yaxis']['range'], (1, 6))

def test_layout_state(self):
layout = Curve([1, 2, 3]) + Curve([2, 4, 6])
state = self._get_plot_state(layout)
self.assertEqual(state['data'][0]['y'], np.array([1, 2, 3]))
self.assertEqual(state['data'][0]['yaxis'], 'y1')
self.assertEqual(state['data'][0]['yaxis'], 'y')
self.assertEqual(state['data'][1]['y'], np.array([2, 4, 6]))
self.assertEqual(state['data'][1]['yaxis'], 'y2')

Expand All @@ -84,13 +84,13 @@ def test_grid_state(self):
for j in [0, 1]})
state = self._get_plot_state(grid)
self.assertEqual(state['data'][0]['y'], np.array([0, 0]))
self.assertEqual(state['data'][0]['xaxis'], 'x1')
self.assertEqual(state['data'][0]['yaxis'], 'y1')
self.assertEqual(state['data'][0]['xaxis'], 'x')
self.assertEqual(state['data'][0]['yaxis'], 'y')
self.assertEqual(state['data'][1]['y'], np.array([1, 0]))
self.assertEqual(state['data'][1]['xaxis'], 'x2')
self.assertEqual(state['data'][1]['yaxis'], 'y1')
self.assertEqual(state['data'][1]['yaxis'], 'y')
self.assertEqual(state['data'][2]['y'], np.array([0, 1]))
self.assertEqual(state['data'][2]['xaxis'], 'x1')
self.assertEqual(state['data'][2]['xaxis'], 'x')
self.assertEqual(state['data'][2]['yaxis'], 'y2')
self.assertEqual(state['data'][3]['y'], np.array([1, 1]))
self.assertEqual(state['data'][3]['xaxis'], 'x2')
Expand Down