Offline Scattergeo plots not working

I believe I can help you out without an example.

Hereā€™s a list of procedures that should work whenever you have an internet connection that can reach out to plot.ly

  1. Make a scattergeo with valid data
  2. Add geo plot to fig
  3. Run plotly.offline.plot(fig)
  4. The figure should show up with the correct map and everything.

Hereā€™s a list of procedures to get this working completely offline without access to internet or plot.ly.

  1. Visit http://cdn.plot.ly/world_110m.json and save the json (upper left hand corner should say ā€˜Saveā€™ in Firefox browser.

  2. Save the .json file in a folder as ā€œworld_110m.jsonā€. I have mine saved in a directory as follows Flask/plotly/topojson

  3. Install flask and flask-cors via pip or Anaconda

  4. Make a simple Flask app (Save it as ā€œPlotlyFlask.pyā€ in the Flask/ directory that you made where you saved the .json file) that can access these topojson files like the following:

import os
import sys
from flask import Flask
from flask_cors import CORS,cross_origin
import json
import argparse

app = Flask(__name__,template_folder='template')
CORS(app)

file_dir = os.path.dirname(os.path.realpath(__file__))

    
@app.route('/<path:relative_path>',methods=['GET','POST'])
@cross_origin()
def get_topojson(relative_path):
    i = json.load(open(os.path.join(file_dir,relative_path),'r'))
    return json.dumps(i)



if __name__ == "__main__":
    my_parser = argparse.ArgumentParser()
    my_parser.version = '0.1.0'
    my_parser.add_argument('-port',default=5000)
    my_parser.add_argument('-host',default='127.0.0.1')
    args = my_parser.parse_args()
    port = args.port
    host = args.host
    app.run(debug = True, port=port, host=host)
  1. Run the PlotlyFlask.py script from a terminal. This will create a web server for you to be able to access the topojsons that you acquire from plot.ly [This is where the default offline mode fails, hence why this is necessary]. Make note of the Hostname and Port that it is running from. My default is 127.0.0.1 [localhost] and port 5000 [just one that i commonly use for testing].

  2. In a completely different python script, create a scattergeo and add it to fig

  3. at the end of your plotting script do

plotly.offline.plot(fig,config={'topojsonURL':'http://127.0.0.1:5000/plotly/topojson/'})

or more generally if you want to write a function just do something like this:

import plotly.graph_objects as go
import plotly
def PLOT(fig,filename,**kwargs):
    host = kwargs.get('host','127.0.0.1')
    port = kwargs.get('port',5000)
    if isinstance(fig,dict):
        fig = go.Figure(fig)
    plotly.offline.plot(fig,filename=filename,config={'topojsonURL':f'http://{host}:{port}/plotly/topojson/'},**kwargs)

Some things to make note of:

The topojsonURL in the config dictionary needs to match the file structure FROM your PlotlyFlask.py to where your topojsons are located. So if your PlotlyFlask.py file is in

MyRandomFolderName/

and the topojson world_110m.json is in

MyRandomFolderName/See/You/There/world_110m.json

then the config would read

config = {'topojsonURL':f'http://{host}:{port}/See/You/There/'}

and everything should work completely offline. Lemme know if you get stuck.

Basically make a Flask app that serves the topojson files and tell plotly to go look for them on your hosted web server instead of going to some website on the internet.

Note, there are more topojson files that need to be downloaded. For the complete set, just replace ā€œworld_110m.jsonā€ from step 1 with each of the following:

world_50m.json
usa_110m.json
usa_50m.json

and all of those should be all that you need with the standard set of projections. There should be no further need to edit the PlotlyFlask.py to get these topojsons to work. it should just give plotly everything it needs. [This really needs to be in the documentations somewhere because plotly is not TRULY offline out of the box.]