Skip to content

offline plot command - fixes https://github.com/plotly/plotly.py/pull/378 #378

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 11, 2016
3 changes: 2 additions & 1 deletion plotly/offline/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
from . offline import (
download_plotlyjs,
init_notebook_mode,
iplot
iplot,
plot
)
237 changes: 173 additions & 64 deletions plotly/offline/offline.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import uuid
import warnings
from pkg_resources import resource_string
import webbrowser

import plotly
from plotly import tools, utils
Expand Down Expand Up @@ -57,6 +58,72 @@ def init_notebook_mode():
'</script>'))


def _plot_html(figure_or_data, show_link, link_text,
validate, default_width, default_height):

figure = tools.return_figure_from_figure_or_data(figure_or_data, validate)

width = figure.get('layout', {}).get('width', default_width)
height = figure.get('layout', {}).get('height', default_height)

try:
float(width)
except (ValueError, TypeError):
pass
else:
width = str(width) + 'px'

try:
float(width)
except (ValueError, TypeError):
pass
else:
width = str(width) + 'px'

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

config = {}
config['showLink'] = show_link
config['linkText'] = link_text
jconfig = json.dumps(config)

# TODO: The get_config 'source of truth' should
# really be somewhere other than plotly.plotly
plotly_platform_url = plotly.plotly.get_config().get('plotly_domain',
'https://plot.ly')
if (plotly_platform_url != 'https://plot.ly' and
link_text == 'Export to plot.ly'):

link_domain = plotly_platform_url\
.replace('https://', '')\
.replace('http://', '')
link_text = link_text.replace('plot.ly', link_domain)

script = 'Plotly.plot("{id}", {data}, {layout}, {config})'.format(
id=plotdivid,
data=jdata,
layout=jlayout,
config=jconfig)

plotly_html_div = (
''
'<div id="{id}" style="height: {height}; width: {width};" '
'class="plotly-graph-div">'
'</div>'
'<script type="text/javascript">'
'window.PLOTLYENV=window.PLOTLYENV || {{}};'
'window.PLOTLYENV.BASE_URL="' + plotly_platform_url + '";'
'{script}'
'</script>'
'').format(
id=plotdivid, script=script,
height=height, width=width)

return plotly_html_div, plotdivid, width, height


def iplot(figure_or_data, show_link=True, link_text='Export to plot.ly',
validate=True):
"""
Expand Down Expand Up @@ -103,76 +170,118 @@ def iplot(figure_or_data, show_link=True, link_text='Export to plot.ly',
raise ImportError('`iplot` can only run inside an IPython Notebook.')

from IPython.display import HTML, display
figure = tools.return_figure_from_figure_or_data(figure_or_data, validate)

width = figure.get('layout', {}).get('width', '100%')
height = figure.get('layout', {}).get('height', 525)
try:
float(width)
except (ValueError, TypeError):
pass
else:
width = str(width) + 'px'
display(HTML(_plot_html(
figure_or_data, show_link, link_text, validate,
'100%', 525)))

try:
float(width)
except (ValueError, TypeError):
pass
else:
width = str(width) + 'px'

plotdivid = uuid.uuid4()
jdata = json.dumps(figure.get('data', []), cls=utils.PlotlyJSONEncoder)
jlayout = json.dumps(figure.get('layout', {}), cls=utils.PlotlyJSONEncoder)
def plot(figure_or_data,
show_link=True, link_text='Export to plot.ly',
validate=True, output_type='file',
include_plotlyjs=True,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, when plotly.js is modularized, we might allow folks to include sub-bundles here. Maybe something like plotlyjs_modules=['scatter', 'bar', 'maps'] which would overwrite the include_plotlyjs argument?
cc @etpinard

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍻

maybe also a include_mathjax flag?

filename='temp-plot.html',
auto_open=True):
""" Create a plotly graph locally as an HTML document or string.

config = {}
config['showLink'] = show_link
config['linkText'] = link_text
jconfig = json.dumps(config)
Example:
```
from plotly.offline import plot
import plotly.graph_objs as go

# TODO: The get_config 'source of truth' should
# really be somewhere other than plotly.plotly
plotly_platform_url = plotly.plotly.get_config().get('plotly_domain',
'https://plot.ly')
if (plotly_platform_url != 'https://plot.ly' and
link_text == 'Export to plot.ly'):
plot([
go.Scatter(x=[1, 2, 3], y=[3, 2 6])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing comma y=[3, 2, 6]

], filename='my-graph.html')
```
More examples below.

link_domain = plotly_platform_url\
.replace('https://', '')\
.replace('http://', '')
link_text = link_text.replace('plot.ly', link_domain)
figure_or_data -- a plotly.graph_objs.Figure or plotly.graph_objs.Data or
dict or list that describes a Plotly graph.
See https://plot.ly/python/ for examples of
graph descriptions.

display(HTML(
'<script type="text/javascript">'
'window.PLOTLYENV=window.PLOTLYENV || {};'
'window.PLOTLYENV.BASE_URL="' + plotly_platform_url + '";'
'</script>'
))

script = '\n'.join([
'Plotly.plot("{id}", {data}, {layout}, {config}).then(function() {{',
' $(".{id}.loading").remove();',
'}})'
]).format(id=plotdivid,
data=jdata,
layout=jlayout,
config=jconfig)

display(HTML(''
'<div class="{id} loading" style="color: rgb(50,50,50);">'
'Drawing...</div>'
'<div id="{id}" style="height: {height}; width: {width};" '
'class="plotly-graph-div">'
'</div>'
'<script type="text/javascript">'
'{script}'
'</script>'
''.format(id=plotdivid, script=script,
height=height, width=width)))


def plot():
""" Configured to work with localhost Plotly graph viewer
Keyword arguments:
show_link (default=True) -- display a link in the bottom-right corner of
of the chart that will export the chart to Plotly Cloud or
Plotly Enterprise
link_text (default='Export to plot.ly') -- the text of export link
validate (default=True) -- validate that all of the keys in the figure
are valid? omit if your version of plotly.js has become outdated
with your version of graph_reference.json or if you need to include
extra, unnecessary keys in your figure.
output_type ('file' | 'div' - default 'file') -- if 'file', then
the graph is saved as a standalone HTML file and `plot`
returns None.
If 'div', then `plot` returns a string that just contains the
HTML <div> that contains the graph and the script to generate the
graph.
Use 'file' if you want to save and view a single graph at a time
in a standalone HTML file.
Use 'div' if you are embedding these graphs in an HTML file with
other graphs or HTML markup, like a HTML report or an website.
include_plotlyjs (default=True) -- If True, include the plotly.js
source code in the output file or string.
Set as False if your HTML file already contains a copy of the plotly.js
library.
filename (default='temp-plot.html') -- The local filename to save the
outputted chart to. If the filename already exists, it will be
overwritten. This argument only applies if `output_type` is 'file'.
auto_open (default=True) -- If True, open the saved file in a
web browser after saving.
This argument only applies if `output_type` is 'file'.
"""
raise NotImplementedError
plot_html, plotdivid, width, height = _plot_html(
figure_or_data, show_link, link_text, validate,
'100%', '100%')

figure = tools.return_figure_from_figure_or_data(figure_or_data, validate)

resize_script = ''
if width == '100%' or height == '100%':
resize_script = (
''
'<script type="text/javascript">'
'window.removeEventListener("resize");'
'window.addEventListener("resize", function(){{'
'console.log("resize");'
'Plotly.Plots.resize(document.getElementById("{id}"));}});'
'</script>'
).format(id=plotdivid)

if output_type == 'file':
filename = 'plotly-temp.html'
with open(filename, 'w') as f:
if include_plotlyjs:
plotly_js_script = ''.join([
'<script type="text/javascript">',
get_plotlyjs(),
'</script>',
])
else:
plotly_js_script = ''

f.write(''.join([
'<html>',
'<head><meta charset="utf-8" /></head>',
'<body>',
plotly_js_script,
plot_html,
resize_script,
'</body>',
'</html>']))

if auto_open:
webbrowser.open('file://' + os.path.abspath(filename))

elif output_type == 'div':
if include_plotlyjs:
return ''.join([
'<div>',
'<script type="text/javascript">',
get_plotlyjs(),
'</script>',
plot_html,
'</div>'
])
else:
return plot_html