|
10 | 10 | import uuid
|
11 | 11 | import warnings
|
12 | 12 | from pkg_resources import resource_string
|
| 13 | +import webbrowser |
13 | 14 |
|
14 | 15 | import plotly
|
15 | 16 | from plotly import tools, utils
|
@@ -57,6 +58,72 @@ def init_notebook_mode():
|
57 | 58 | '</script>'))
|
58 | 59 |
|
59 | 60 |
|
| 61 | +def _plot_html(figure_or_data, show_link, link_text, |
| 62 | + validate, default_width, default_height): |
| 63 | + |
| 64 | + figure = tools.return_figure_from_figure_or_data(figure_or_data, validate) |
| 65 | + |
| 66 | + width = figure.get('layout', {}).get('width', default_width) |
| 67 | + height = figure.get('layout', {}).get('height', default_height) |
| 68 | + |
| 69 | + try: |
| 70 | + float(width) |
| 71 | + except (ValueError, TypeError): |
| 72 | + pass |
| 73 | + else: |
| 74 | + width = str(width) + 'px' |
| 75 | + |
| 76 | + try: |
| 77 | + float(width) |
| 78 | + except (ValueError, TypeError): |
| 79 | + pass |
| 80 | + else: |
| 81 | + width = str(width) + 'px' |
| 82 | + |
| 83 | + plotdivid = uuid.uuid4() |
| 84 | + jdata = json.dumps(figure.get('data', []), cls=utils.PlotlyJSONEncoder) |
| 85 | + jlayout = json.dumps(figure.get('layout', {}), cls=utils.PlotlyJSONEncoder) |
| 86 | + |
| 87 | + config = {} |
| 88 | + config['showLink'] = show_link |
| 89 | + config['linkText'] = link_text |
| 90 | + jconfig = json.dumps(config) |
| 91 | + |
| 92 | + # TODO: The get_config 'source of truth' should |
| 93 | + # really be somewhere other than plotly.plotly |
| 94 | + plotly_platform_url = plotly.plotly.get_config().get('plotly_domain', |
| 95 | + 'https://plot.ly') |
| 96 | + if (plotly_platform_url != 'https://plot.ly' and |
| 97 | + link_text == 'Export to plot.ly'): |
| 98 | + |
| 99 | + link_domain = plotly_platform_url\ |
| 100 | + .replace('https://', '')\ |
| 101 | + .replace('http://', '') |
| 102 | + link_text = link_text.replace('plot.ly', link_domain) |
| 103 | + |
| 104 | + script = 'Plotly.plot("{id}", {data}, {layout}, {config})'.format( |
| 105 | + id=plotdivid, |
| 106 | + data=jdata, |
| 107 | + layout=jlayout, |
| 108 | + config=jconfig) |
| 109 | + |
| 110 | + plotly_html_div = ( |
| 111 | + '' |
| 112 | + '<div id="{id}" style="height: {height}; width: {width};" ' |
| 113 | + 'class="plotly-graph-div">' |
| 114 | + '</div>' |
| 115 | + '<script type="text/javascript">' |
| 116 | + 'window.PLOTLYENV=window.PLOTLYENV || {{}};' |
| 117 | + 'window.PLOTLYENV.BASE_URL="' + plotly_platform_url + '";' |
| 118 | + '{script}' |
| 119 | + '</script>' |
| 120 | + '').format( |
| 121 | + id=plotdivid, script=script, |
| 122 | + height=height, width=width) |
| 123 | + |
| 124 | + return plotly_html_div, plotdivid, width, height |
| 125 | + |
| 126 | + |
60 | 127 | def iplot(figure_or_data, show_link=True, link_text='Export to plot.ly',
|
61 | 128 | validate=True):
|
62 | 129 | """
|
@@ -103,76 +170,118 @@ def iplot(figure_or_data, show_link=True, link_text='Export to plot.ly',
|
103 | 170 | raise ImportError('`iplot` can only run inside an IPython Notebook.')
|
104 | 171 |
|
105 | 172 | from IPython.display import HTML, display
|
106 |
| - figure = tools.return_figure_from_figure_or_data(figure_or_data, validate) |
107 | 173 |
|
108 |
| - width = figure.get('layout', {}).get('width', '100%') |
109 |
| - height = figure.get('layout', {}).get('height', 525) |
110 |
| - try: |
111 |
| - float(width) |
112 |
| - except (ValueError, TypeError): |
113 |
| - pass |
114 |
| - else: |
115 |
| - width = str(width) + 'px' |
| 174 | + display(HTML(_plot_html( |
| 175 | + figure_or_data, show_link, link_text, validate, |
| 176 | + '100%', 525))) |
116 | 177 |
|
117 |
| - try: |
118 |
| - float(width) |
119 |
| - except (ValueError, TypeError): |
120 |
| - pass |
121 |
| - else: |
122 |
| - width = str(width) + 'px' |
123 | 178 |
|
124 |
| - plotdivid = uuid.uuid4() |
125 |
| - jdata = json.dumps(figure.get('data', []), cls=utils.PlotlyJSONEncoder) |
126 |
| - jlayout = json.dumps(figure.get('layout', {}), cls=utils.PlotlyJSONEncoder) |
| 179 | +def plot(figure_or_data, |
| 180 | + show_link=True, link_text='Export to plot.ly', |
| 181 | + validate=True, output_type='file', |
| 182 | + include_plotlyjs=True, |
| 183 | + filename='temp-plot.html', |
| 184 | + auto_open=True): |
| 185 | + """ Create a plotly graph locally as an HTML document or string. |
127 | 186 |
|
128 |
| - config = {} |
129 |
| - config['showLink'] = show_link |
130 |
| - config['linkText'] = link_text |
131 |
| - jconfig = json.dumps(config) |
| 187 | + Example: |
| 188 | + ``` |
| 189 | + from plotly.offline import plot |
| 190 | + import plotly.graph_objs as go |
132 | 191 |
|
133 |
| - # TODO: The get_config 'source of truth' should |
134 |
| - # really be somewhere other than plotly.plotly |
135 |
| - plotly_platform_url = plotly.plotly.get_config().get('plotly_domain', |
136 |
| - 'https://plot.ly') |
137 |
| - if (plotly_platform_url != 'https://plot.ly' and |
138 |
| - link_text == 'Export to plot.ly'): |
| 192 | + plot([ |
| 193 | + go.Scatter(x=[1, 2, 3], y=[3, 2 6]) |
| 194 | + ], filename='my-graph.html') |
| 195 | + ``` |
| 196 | + More examples below. |
139 | 197 |
|
140 |
| - link_domain = plotly_platform_url\ |
141 |
| - .replace('https://', '')\ |
142 |
| - .replace('http://', '') |
143 |
| - link_text = link_text.replace('plot.ly', link_domain) |
| 198 | + figure_or_data -- a plotly.graph_objs.Figure or plotly.graph_objs.Data or |
| 199 | + dict or list that describes a Plotly graph. |
| 200 | + See https://plot.ly/python/ for examples of |
| 201 | + graph descriptions. |
144 | 202 |
|
145 |
| - display(HTML( |
146 |
| - '<script type="text/javascript">' |
147 |
| - 'window.PLOTLYENV=window.PLOTLYENV || {};' |
148 |
| - 'window.PLOTLYENV.BASE_URL="' + plotly_platform_url + '";' |
149 |
| - '</script>' |
150 |
| - )) |
151 |
| - |
152 |
| - script = '\n'.join([ |
153 |
| - 'Plotly.plot("{id}", {data}, {layout}, {config}).then(function() {{', |
154 |
| - ' $(".{id}.loading").remove();', |
155 |
| - '}})' |
156 |
| - ]).format(id=plotdivid, |
157 |
| - data=jdata, |
158 |
| - layout=jlayout, |
159 |
| - config=jconfig) |
160 |
| - |
161 |
| - display(HTML('' |
162 |
| - '<div class="{id} loading" style="color: rgb(50,50,50);">' |
163 |
| - 'Drawing...</div>' |
164 |
| - '<div id="{id}" style="height: {height}; width: {width};" ' |
165 |
| - 'class="plotly-graph-div">' |
166 |
| - '</div>' |
167 |
| - '<script type="text/javascript">' |
168 |
| - '{script}' |
169 |
| - '</script>' |
170 |
| - ''.format(id=plotdivid, script=script, |
171 |
| - height=height, width=width))) |
172 |
| - |
173 |
| - |
174 |
| -def plot(): |
175 |
| - """ Configured to work with localhost Plotly graph viewer |
| 203 | + Keyword arguments: |
| 204 | + show_link (default=True) -- display a link in the bottom-right corner of |
| 205 | + of the chart that will export the chart to Plotly Cloud or |
| 206 | + Plotly Enterprise |
| 207 | + link_text (default='Export to plot.ly') -- the text of export link |
| 208 | + validate (default=True) -- validate that all of the keys in the figure |
| 209 | + are valid? omit if your version of plotly.js has become outdated |
| 210 | + with your version of graph_reference.json or if you need to include |
| 211 | + extra, unnecessary keys in your figure. |
| 212 | + output_type ('file' | 'div' - default 'file') -- if 'file', then |
| 213 | + the graph is saved as a standalone HTML file and `plot` |
| 214 | + returns None. |
| 215 | + If 'div', then `plot` returns a string that just contains the |
| 216 | + HTML <div> that contains the graph and the script to generate the |
| 217 | + graph. |
| 218 | + Use 'file' if you want to save and view a single graph at a time |
| 219 | + in a standalone HTML file. |
| 220 | + Use 'div' if you are embedding these graphs in an HTML file with |
| 221 | + other graphs or HTML markup, like a HTML report or an website. |
| 222 | + include_plotlyjs (default=True) -- If True, include the plotly.js |
| 223 | + source code in the output file or string. |
| 224 | + Set as False if your HTML file already contains a copy of the plotly.js |
| 225 | + library. |
| 226 | + filename (default='temp-plot.html') -- The local filename to save the |
| 227 | + outputted chart to. If the filename already exists, it will be |
| 228 | + overwritten. This argument only applies if `output_type` is 'file'. |
| 229 | + auto_open (default=True) -- If True, open the saved file in a |
| 230 | + web browser after saving. |
| 231 | + This argument only applies if `output_type` is 'file'. |
176 | 232 | """
|
177 |
| - raise NotImplementedError |
| 233 | + plot_html, plotdivid, width, height = _plot_html( |
| 234 | + figure_or_data, show_link, link_text, validate, |
| 235 | + '100%', '100%') |
| 236 | + |
| 237 | + figure = tools.return_figure_from_figure_or_data(figure_or_data, validate) |
| 238 | + |
| 239 | + resize_script = '' |
| 240 | + if width == '100%' or height == '100%': |
| 241 | + resize_script = ( |
| 242 | + '' |
| 243 | + '<script type="text/javascript">' |
| 244 | + 'window.removeEventListener("resize");' |
| 245 | + 'window.addEventListener("resize", function(){{' |
| 246 | + 'console.log("resize");' |
| 247 | + 'Plotly.Plots.resize(document.getElementById("{id}"));}});' |
| 248 | + '</script>' |
| 249 | + ).format(id=plotdivid) |
| 250 | + |
| 251 | + if output_type == 'file': |
| 252 | + filename = 'plotly-temp.html' |
| 253 | + with open(filename, 'w') as f: |
| 254 | + if include_plotlyjs: |
| 255 | + plotly_js_script = ''.join([ |
| 256 | + '<script type="text/javascript">', |
| 257 | + get_plotlyjs(), |
| 258 | + '</script>', |
| 259 | + ]) |
| 260 | + else: |
| 261 | + plotly_js_script = '' |
| 262 | + |
| 263 | + f.write(''.join([ |
| 264 | + '<html>', |
| 265 | + '<head><meta charset="utf-8" /></head>', |
| 266 | + '<body>', |
| 267 | + plotly_js_script, |
| 268 | + plot_html, |
| 269 | + resize_script, |
| 270 | + '</body>', |
| 271 | + '</html>'])) |
| 272 | + |
| 273 | + if auto_open: |
| 274 | + webbrowser.open('file://' + os.path.abspath(filename)) |
178 | 275 |
|
| 276 | + elif output_type == 'div': |
| 277 | + if include_plotlyjs: |
| 278 | + return ''.join([ |
| 279 | + '<div>', |
| 280 | + '<script type="text/javascript">', |
| 281 | + get_plotlyjs(), |
| 282 | + '</script>', |
| 283 | + plot_html, |
| 284 | + '</div>' |
| 285 | + ]) |
| 286 | + else: |
| 287 | + return plot_html |
0 commit comments