Skip to content

Commit 079c924

Browse files
author
Kevin Yan
authored
Merge pull request #494 from plotly/download-image-offline
added option to download an image of the most recent plot
2 parents 36f7e3c + 4235cd4 commit 079c924

File tree

1 file changed

+141
-10
lines changed

1 file changed

+141
-10
lines changed

plotly/offline/offline.py

+141-10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import uuid
1111
import warnings
1212
from pkg_resources import resource_string
13+
import time
1314
import webbrowser
1415

1516
import plotly
@@ -31,6 +32,8 @@
3132

3233
__PLOTLY_OFFLINE_INITIALIZED = False
3334

35+
__IMAGE_FORMATS = ['jpeg', 'png', 'webp', 'svg']
36+
3437

3538
def download_plotlyjs(download_url):
3639
warnings.warn('''
@@ -46,6 +49,49 @@ def get_plotlyjs():
4649
plotlyjs = resource_string('plotly', path).decode('utf-8')
4750
return plotlyjs
4851

52+
def get_image_download_script(caller):
53+
"""
54+
This function will return a script that will download an image of a Plotly
55+
plot.
56+
57+
Keyword Arguments:
58+
caller ('plot', 'iplot') -- specifies which function made the call for the
59+
download script. If `iplot`, then an extra condition is added into the
60+
download script to ensure that download prompts aren't initiated on
61+
page reloads.
62+
"""
63+
64+
if caller == 'iplot':
65+
check_start = 'if(document.readyState == \'complete\') {{'
66+
check_end = '}}'
67+
elif caller == 'plot':
68+
check_start = ''
69+
check_end = ''
70+
else:
71+
raise ValueError('caller should only be one of `iplot` or `plot`')
72+
73+
return(
74+
('<script>'
75+
'function downloadimage(format, height, width,'
76+
' filename) {{'
77+
'var p = document.getElementById(\'{plot_id}\');'
78+
'Plotly.downloadImage(p, {{format: format, height: height, '
79+
'width: width, filename: filename}});'
80+
'}};' +
81+
check_start +
82+
'if(confirm(\'Do you want to save this image as '
83+
'{filename}.{format}?\\n\\n'
84+
'For higher resolution images and more export options, '
85+
'consider making requests to our image servers. Type: '
86+
'help(py.image) for more details.'
87+
'\')) {{'
88+
'downloadimage(\'{format}\', {height}, {width}, '
89+
'\'{filename}\');}}' +
90+
check_end +
91+
'</script>'
92+
)
93+
)
94+
4995

5096
def init_notebook_mode(connected=False):
5197
"""
@@ -114,8 +160,8 @@ def init_notebook_mode(connected=False):
114160
__PLOTLY_OFFLINE_INITIALIZED = True
115161

116162

117-
def _plot_html(figure_or_data, show_link, link_text,
118-
validate, default_width, default_height, global_requirejs):
163+
def _plot_html(figure_or_data, show_link, link_text, validate,
164+
default_width, default_height, global_requirejs):
119165

120166
figure = tools.return_figure_from_figure_or_data(figure_or_data, validate)
121167

@@ -185,9 +231,9 @@ def _plot_html(figure_or_data, show_link, link_text,
185231

186232
return plotly_html_div, plotdivid, width, height
187233

188-
189234
def iplot(figure_or_data, show_link=True, link_text='Export to plot.ly',
190-
validate=True):
235+
validate=True, image=None, filename='plot_image', image_width=800,
236+
image_height=600):
191237
"""
192238
Draw plotly graphs inside an IPython notebook without
193239
connecting to an external server.
@@ -210,12 +256,23 @@ def iplot(figure_or_data, show_link=True, link_text='Export to plot.ly',
210256
has become outdated with your version of
211257
graph_reference.json or if you need to include
212258
extra, unnecessary keys in your figure.
259+
image (default=None |'png' |'jpeg' |'svg' |'webp') -- This parameter sets
260+
the format of the image to be downloaded, if we choose to download an
261+
image. This parameter has a default value of None indicating that no
262+
image should be downloaded.
263+
filename (default='plot') -- Sets the name of the file your image
264+
will be saved to. The extension should not be included.
265+
image_height (default=600) -- Specifies the height of the image in `px`.
266+
image_width (default=800) -- Specifies the width of the image in `px`.
213267
214268
Example:
215269
```
216270
from plotly.offline import init_notebook_mode, iplot
217271
init_notebook_mode()
218272
iplot([{'x': [1, 2, 3], 'y': [5, 2, 7]}])
273+
# We can also download an image of the plot by setting the image to the
274+
format you want. e.g. `image='png'`
275+
iplot([{'x': [1, 2, 3], 'y': [5, 2, 7]}], image='png')
219276
```
220277
"""
221278
if not __PLOTLY_OFFLINE_INITIALIZED:
@@ -236,13 +293,30 @@ def iplot(figure_or_data, show_link=True, link_text='Export to plot.ly',
236293

237294
display(HTML(plot_html))
238295

296+
if image:
297+
if image not in __IMAGE_FORMATS:
298+
raise ValueError('The image parameter must be one of the following'
299+
': {}'.format(__IMAGE_FORMATS)
300+
)
301+
# if image is given, and is a valid format, we will download the image
302+
script = get_image_download_script('iplot').format(format=image,
303+
width=image_width,
304+
height=image_height,
305+
filename=filename,
306+
plot_id=plotdivid)
307+
# allow time for the plot to draw
308+
time.sleep(1)
309+
# inject code to download an image of the plot
310+
display(HTML(script))
311+
239312

240313
def plot(figure_or_data,
241314
show_link=True, link_text='Export to plot.ly',
242315
validate=True, output_type='file',
243316
include_plotlyjs=True,
244-
filename='temp-plot.html',
245-
auto_open=True):
317+
filename='temp-plot.html', auto_open=True,
318+
image=None, image_filename='plot_image',
319+
image_width=800, image_height=600):
246320
""" Create a plotly graph locally as an HTML document or string.
247321
248322
Example:
@@ -251,6 +325,10 @@ def plot(figure_or_data,
251325
import plotly.graph_objs as go
252326
253327
plot([go.Scatter(x=[1, 2, 3], y=[3, 2, 6])], filename='my-graph.html')
328+
# We can also download an image of the plot by setting the image parameter
329+
# to the image format we want
330+
plot([go.Scatter(x=[1, 2, 3], y=[3, 2, 6])], filename='my-graph.html'
331+
image='jpeg')
254332
```
255333
More examples below.
256334
@@ -288,6 +366,14 @@ def plot(figure_or_data,
288366
auto_open (default=True) -- If True, open the saved file in a
289367
web browser after saving.
290368
This argument only applies if `output_type` is 'file'.
369+
image (default=None |'png' |'jpeg' |'svg' |'webp') -- This parameter sets
370+
the format of the image to be downloaded, if we choose to download an
371+
image. This parameter has a default value of None indicating that no
372+
image should be downloaded.
373+
image_filename (default='plot_image') -- Sets the name of the file your image
374+
will be saved to. The extension should not be included.
375+
image_height (default=600) -- Specifies the height of the image in `px`.
376+
image_width (default=800) -- Specifies the width of the image in `px`.
291377
"""
292378
if output_type not in ['div', 'file']:
293379
raise ValueError(
@@ -325,13 +411,30 @@ def plot(figure_or_data,
325411
else:
326412
plotly_js_script = ''
327413

414+
if image:
415+
if image not in __IMAGE_FORMATS:
416+
raise ValueError('The image parameter must be one of the '
417+
'following: {}'.format(__IMAGE_FORMATS)
418+
)
419+
# if the check passes then download script is injected.
420+
# write the download script:
421+
script = get_image_download_script('plot')
422+
script = script.format(format=image,
423+
width=image_width,
424+
height=image_height,
425+
filename=image_filename,
426+
plot_id=plotdivid)
427+
else:
428+
script = ''
429+
328430
f.write(''.join([
329431
'<html>',
330432
'<head><meta charset="utf-8" /></head>',
331433
'<body>',
332434
plotly_js_script,
333435
plot_html,
334436
resize_script,
437+
script,
335438
'</body>',
336439
'</html>']))
337440

@@ -358,7 +461,9 @@ def plot(figure_or_data,
358461
def plot_mpl(mpl_fig, resize=False, strip_style=False,
359462
verbose=False, show_link=True, link_text='Export to plot.ly',
360463
validate=True, output_type='file', include_plotlyjs=True,
361-
filename='temp-plot.html', auto_open=True):
464+
filename='temp-plot.html', auto_open=True,
465+
image=None, image_filename='plot_image',
466+
image_height=600, image_width=800):
362467
"""
363468
Convert a matplotlib figure to a Plotly graph stored locally as HTML.
364469
@@ -402,6 +507,14 @@ def plot_mpl(mpl_fig, resize=False, strip_style=False,
402507
auto_open (default=True) -- If True, open the saved file in a
403508
web browser after saving.
404509
This argument only applies if `output_type` is 'file'.
510+
image (default=None |'png' |'jpeg' |'svg' |'webp') -- This parameter sets
511+
the format of the image to be downloaded, if we choose to download an
512+
image. This parameter has a default value of None indicating that no
513+
image should be downloaded.
514+
image_filename (default='plot_image') -- Sets the name of the file your
515+
image will be saved to. The extension should not be included.
516+
image_height (default=600) -- Specifies the height of the image in `px`.
517+
image_width (default=800) -- Specifies the width of the image in `px`.
405518
406519
Example:
407520
```
@@ -416,16 +529,22 @@ def plot_mpl(mpl_fig, resize=False, strip_style=False,
416529
plt.plot(x, y, "o")
417530
418531
plot_mpl(fig)
532+
# If you want to to download an image of the figure as well
533+
plot_mpl(fig, image='png')
419534
```
420535
"""
421536
plotly_plot = tools.mpl_to_plotly(mpl_fig, resize, strip_style, verbose)
422537
return plot(plotly_plot, show_link, link_text, validate, output_type,
423-
include_plotlyjs, filename, auto_open)
538+
include_plotlyjs, filename, auto_open,
539+
image=image, image_filename=image_filename,
540+
image_height=image_height, image_width=image_width)
424541

425542

426543
def iplot_mpl(mpl_fig, resize=False, strip_style=False,
427544
verbose=False, show_link=True,
428-
link_text='Export to plot.ly', validate=True):
545+
link_text='Export to plot.ly', validate=True,
546+
image=None, image_filename='plot_image',
547+
image_height=600, image_width=800):
429548
"""
430549
Convert a matplotlib figure to a plotly graph and plot inside an IPython
431550
notebook without connecting to an external server.
@@ -454,6 +573,14 @@ def iplot_mpl(mpl_fig, resize=False, strip_style=False,
454573
has become outdated with your version of
455574
graph_reference.json or if you need to include
456575
extra, unnecessary keys in your figure.
576+
image (default=None |'png' |'jpeg' |'svg' |'webp') -- This parameter sets
577+
the format of the image to be downloaded, if we choose to download an
578+
image. This parameter has a default value of None indicating that no
579+
image should be downloaded.
580+
image_filename (default='plot_image') -- Sets the name of the file your
581+
image will be saved to. The extension should not be included.
582+
image_height (default=600) -- Specifies the height of the image in `px`.
583+
image_width (default=800) -- Specifies the width of the image in `px`.
457584
458585
Example:
459586
```
@@ -467,10 +594,14 @@ def iplot_mpl(mpl_fig, resize=False, strip_style=False,
467594
468595
init_notebook_mode()
469596
iplot_mpl(fig)
597+
# and if you want to download an image of the figure as well
598+
iplot_mpl(fig, image='jpeg')
470599
```
471600
"""
472601
plotly_plot = tools.mpl_to_plotly(mpl_fig, resize, strip_style, verbose)
473-
return iplot(plotly_plot, show_link, link_text, validate)
602+
return iplot(plotly_plot, show_link, link_text, validate,
603+
image=image, filename=image_filename,
604+
image_height=image_height, image_width=image_width)
474605

475606

476607
def enable_mpl_offline(resize=False, strip_style=False,

0 commit comments

Comments
 (0)