Save fig as html using jupyterlab/FigureWidget?


#1

Missing something majorly simple, but how do we accomplish py.plot(fig, filename=‘name.html’) (i.e. saving a plot or mapbox plot as an html) with FigureWidget/in jupyterlab?

Additionally, are there additional components for saving a scattermapbox as an html or png? When I click on the screenshot icon in my scattermapbox, I only get an output of the added title and legend on a white box.


#2

Hi @melmel,

FigureWidget is essentially a Figure subclass so you can use the same plot/iplot methods on a FigureWidget as well. (Note that any Python callbacks that are registered on the FigureWidget won’t be active in the static HTML version because there’s no Python kernel available there.)

Hmm, I’m not sure what might be going on with your scattermapbox plot. Clicking the save image modebar button should work without additional configuration. Does this simple example give you the same problem https://plot.ly/python/scattermapbox/#basic-example?

If you want to try saving the image programmatically using orca (https://plot.ly/python/static-image-export/) then you need to configure orca with your mapbox access token (https://plot.ly/python/orca-management/#other-configuration-settings).

Hope that helps!
-Jon


#3

Thanks, @jmmease ! I can reproduce the map in the mapbox example if I only call iplot(fig) , but get an error when I try to call py.iplot(fig, filename='Montreal Mapbox'. It seems like the filename part might be the issue?

Here’s the error and the list of packages that I have in my venv (maybe I’m missing something to work with mapbox?):

Error:

---------------------------------------------------------------------------
gaierror                                  Traceback (most recent call last)
/anaconda3/lib/python3.6/site-packages/urllib3/connection.py in _new_conn(self)
    170             conn = connection.create_connection(
--> 171                 (self._dns_host, self.port), self.timeout, **extra_kw)
    172 

/anaconda3/lib/python3.6/site-packages/urllib3/util/connection.py in create_connection(address, timeout, source_address, socket_options)
     55 
---> 56     for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
     57         af, socktype, proto, canonname, sa = res

/anaconda3/lib/python3.6/socket.py in getaddrinfo(host, port, family, type, proto, flags)
    744     addrlist = []
--> 745     for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
    746         af, socktype, proto, canonname, sa = res

gaierror: [Errno 8] nodename nor servname provided, or not known

During handling of the above exception, another exception occurred:

NewConnectionError                        Traceback (most recent call last)
/anaconda3/lib/python3.6/site-packages/urllib3/connectionpool.py in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
    599                                                   body=body, headers=headers,
--> 600                                                   chunked=chunked)
    601 

/anaconda3/lib/python3.6/site-packages/urllib3/connectionpool.py in _make_request(self, conn, method, url, timeout, chunked, **httplib_request_kw)
    353         else:
--> 354             conn.request(method, url, **httplib_request_kw)
    355 

/anaconda3/lib/python3.6/http/client.py in request(self, method, url, body, headers, encode_chunked)
   1238         """Send a complete request to the server."""
-> 1239         self._send_request(method, url, body, headers, encode_chunked)
   1240 

/anaconda3/lib/python3.6/http/client.py in _send_request(self, method, url, body, headers, encode_chunked)
   1284             body = _encode(body, 'body')
-> 1285         self.endheaders(body, encode_chunked=encode_chunked)
   1286 

/anaconda3/lib/python3.6/http/client.py in endheaders(self, message_body, encode_chunked)
   1233             raise CannotSendHeader()
-> 1234         self._send_output(message_body, encode_chunked=encode_chunked)
   1235 

/anaconda3/lib/python3.6/http/client.py in _send_output(self, message_body, encode_chunked)
   1025         del self._buffer[:]
-> 1026         self.send(msg)
   1027 

/anaconda3/lib/python3.6/http/client.py in send(self, data)
    963             if self.auto_open:
--> 964                 self.connect()
    965             else:

/anaconda3/lib/python3.6/site-packages/urllib3/connection.py in connect(self)
    195     def connect(self):
--> 196         conn = self._new_conn()
    197         self._prepare_conn(conn)

/anaconda3/lib/python3.6/site-packages/urllib3/connection.py in _new_conn(self)
    179             raise NewConnectionError(
--> 180                 self, "Failed to establish a new connection: %s" % e)
    181 

NewConnectionError: <urllib3.connection.HTTPConnection object at 0x1153b01d0>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known

During handling of the above exception, another exception occurred:

MaxRetryError                             Traceback (most recent call last)
/anaconda3/lib/python3.6/site-packages/requests/adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
    444                     retries=self.max_retries,
--> 445                     timeout=timeout
    446                 )

/anaconda3/lib/python3.6/site-packages/urllib3/connectionpool.py in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
    637             retries = retries.increment(method, url, error=e, _pool=self,
--> 638                                         _stacktrace=sys.exc_info()[2])
    639             retries.sleep()

/anaconda3/lib/python3.6/site-packages/urllib3/util/retry.py in increment(self, method, url, response, error, _pool, _stacktrace)
    397         if new_retry.is_exhausted():
--> 398             raise MaxRetryError(_pool, url, error or ResponseError(cause))
    399 

MaxRetryError: HTTPConnectionPool(host='type-here.com', port=80): Max retries exceeded with url: /clientresp (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x1153b01d0>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known',))

During handling of the above exception, another exception occurred:

ConnectionError                           Traceback (most recent call last)
/anaconda3/lib/python3.6/site-packages/plotly/api/v1/utils.py in request(method, url, **kwargs)
     81     try:
---> 82         response = requests.request(method, url, **kwargs)
     83     except RequestException as e:

/anaconda3/lib/python3.6/site-packages/requests/api.py in request(method, url, **kwargs)
     57     with sessions.Session() as session:
---> 58         return session.request(method=method, url=url, **kwargs)
     59 

/anaconda3/lib/python3.6/site-packages/requests/sessions.py in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    511         send_kwargs.update(settings)
--> 512         resp = self.send(prep, **send_kwargs)
    513 

/anaconda3/lib/python3.6/site-packages/requests/sessions.py in send(self, request, **kwargs)
    621         # Send the request
--> 622         r = adapter.send(request, **kwargs)
    623 

/anaconda3/lib/python3.6/site-packages/requests/adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
    512 
--> 513             raise ConnectionError(e, request=request)
    514 

ConnectionError: HTTPConnectionPool(host='type-here.com', port=80): Max retries exceeded with url: /clientresp (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x1153b01d0>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known',))

During handling of the above exception, another exception occurred:

PlotlyRequestError                        Traceback (most recent call last)
<ipython-input-14-8948ce56f28e> in <module>
----> 1 py.iplot(fig, filename='Montreal Mapbox')

/anaconda3/lib/python3.6/site-packages/plotly/plotly/plotly.py in iplot(figure_or_data, **plot_options)
    140     if 'auto_open' not in plot_options:
    141         plot_options['auto_open'] = False
--> 142     url = plot(figure_or_data, **plot_options)
    143 
    144     if isinstance(figure_or_data, dict):

/anaconda3/lib/python3.6/site-packages/plotly/plotly/plotly.py in plot(figure_or_data, validate, **plot_options)
    237     data = fig.get('data', [])
    238     plot_options['layout'] = fig.get('layout', {})
--> 239     response = v1.clientresp(data, **plot_options)
    240 
    241     # Check if the url needs a secret key

/anaconda3/lib/python3.6/site-packages/plotly/api/v1/clientresp.py in clientresp(data, **kwargs)
     33 
     34     url = '{plotly_domain}/clientresp'.format(**cfg)
---> 35     response = request('post', url, data=payload)
     36 
     37     # Old functionality, just keeping it around.

/anaconda3/lib/python3.6/site-packages/retrying.py in wrapped_f(*args, **kw)
     47             @six.wraps(f)
     48             def wrapped_f(*args, **kw):
---> 49                 return Retrying(*dargs, **dkw).call(f, *args, **kw)
     50 
     51             return wrapped_f

/anaconda3/lib/python3.6/site-packages/retrying.py in call(self, fn, *args, **kwargs)
    204 
    205             if not self.should_reject(attempt):
--> 206                 return attempt.get(self._wrap_exception)
    207 
    208             delay_since_first_attempt_ms = int(round(time.time() * 1000)) - start_time

/anaconda3/lib/python3.6/site-packages/retrying.py in get(self, wrap_exception)
    245                 raise RetryError(self)
    246             else:
--> 247                 six.reraise(self.value[0], self.value[1], self.value[2])
    248         else:
    249             return self.value

/anaconda3/lib/python3.6/site-packages/six.py in reraise(tp, value, tb)
    691             if value.__traceback__ is not tb:
    692                 raise value.with_traceback(tb)
--> 693             raise value
    694         finally:
    695             value = None

/anaconda3/lib/python3.6/site-packages/retrying.py in call(self, fn, *args, **kwargs)
    198         while True:
    199             try:
--> 200                 attempt = Attempt(fn(*args, **kwargs), attempt_number, False)
    201             except:
    202                 tb = sys.exc_info()

/anaconda3/lib/python3.6/site-packages/plotly/api/v1/utils.py in request(method, url, **kwargs)
     87         status_code = response.status_code if response else None
     88         content = response.content if response else 'No content'
---> 89         raise exceptions.PlotlyRequestError(message, status_code, content)
     90     validate_response(response)
     91     return response

PlotlyRequestError: No message

List of packages using:

appnope==0.1.0
asn1crypto==0.24.0
backcall==0.1.0
cachetools==3.0.0
certifi==2018.10.15
cffi==1.11.5
chardet==3.0.4
Click==7.0
cryptography==2.4.2
cycler==0.10.0
Cython==0.29.1
decorator==4.3.0
descartes==1.1.0
geocoder==1.22.4
geojsonio==0.0.3
github3.py==1.2.0
google-api-python-client==1.7.4
google-auth==1.6.1
google-auth-httplib2==0.0.3
googlemaps==3.0.2
httplib2==0.12.0
idna==2.7
ipykernel==5.1.0
ipython==7.1.1
ipython-genutils==0.2.0
jedi==0.13.1
jupyter-client==5.2.3
jupyter-core==4.4.0
jwcrypto==0.6.0
kiwisolver==1.0.1
matplotlib==3.0.2
numpy==1.15.4
pandas==0.23.4
parso==0.3.1
pexpect==4.6.0
pickleshare==0.7.5
prompt-toolkit==2.0.7
ptyprocess==0.6.0
pyasn1==0.4.4
pyasn1-modules==0.2.2
pycparser==2.19
Pygments==2.2.0
pyparsing==2.3.0
pyshp==2.0.1
python-dateutil==2.7.5
pytz==2018.7
pyzmq==17.1.2
ratelim==0.1.6
requests==2.20.1
rsa==4.0
Shapely==1.5.17.post1
six==1.11.0
tornado==5.1.1
traitlets==4.3.2
uritemplate==3.0.0
urllib3==1.24.1
wcwidth==0.1.7

#4

Hmm, you shouldn’t need anything extra installed for mapbox plots. Does py.iplot work for you for other non-mapbox trace types?

-Jon


#5

No–keep getting the same error, associated with connection errors (with plotly, even in offline mode?).

Partial error message below:

...
gaierror: [Errno 8] nodename nor servname provided, or not known
...
NewConnectionError: <urllib3.connection.HTTPConnection object at 0x1a1df7fb70>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known
...
MaxRetryError: HTTPConnectionPool(host='type-here.com', port=80): Max retries exceeded with url: /clientresp (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x1a1df7fb70>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known',))
...
ConnectionError: HTTPConnectionPool(host='type-here.com', port=80): Max retries exceeded with url: /clientresp (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x1a1df7fb70>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known',))
...
PlotlyRequestError: No message

The png screenshots work with non-mapbox plots, and I can open both types of plots in Chart Studio and save as both png and html files from there.


#6

Hi @melmel,

What are you importing for these examples? If you’re saving to HTML using plotly.offline.plot (rather than plotly.plotly.plot) then there shouldn’t be any external connections involved.

Here’s a minimal example of saving a figure to HTML in offline mode.

import plotly.graph_objs as go
from plotly.offline import plot

plot(go.Figure(data=[go.Scatter(y=[1, 3, 2])]), filename='fig.html')

Does this work for you?
-Jon


#7

Ah yes this works! I had from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot at one point in troubleshooting, but kept switching things around.

Thanks for your help!