1
votes

After being fed up with Matplotlib, I'm looking into using Plotly. I have a simple plot made, however, whenever I try to create the plot the browser opens up and it is looking for "cdn cloudflare" or something like that. It hangs here for about a minute before finally showing some plots. Some plots don't even render such as the Scattergeo. Any idea on how to strip these dependencies? I'm working on a network that has no outside connection.

Note: This is test code. Change the if False to if True to run that portion of the code. I'm also using Plotly version 4.7.1

Here's some example code.

import plotly
import plotly.graph_objects as go
import plotly.io as pio
import numpy as np
import pandas as pd
pio.renderers.default = "browser"

size = 100
#Stacked Plot
if False:
    fig = go.Figure()

    #Data Creation
    y1 = np.random.randint(0,50,size)
    y2 = 50 - np.random.randint(0,25,size)
    y3 = 100 - (y2+y1)
    x = np.linspace(0,100,size)

    #Plot Essentials
    g = [go.Scatter(x=x,y=y1,mode='lines+markers',stackgroup='1',name='money'),
              go.Scatter(x=x,y=y2,mode='lines+markers',stackgroup='1',name='credit'),
              go.Scatter(x=x,y=y3,mode='lines+markers',stackgroup='1',name='IOU')]

    for s in g:
        fig.add_trace(s)
    fig.update_layout(title=dict(text='Resource Plot'),
                          xaxis = dict(title = dict(text='Time (s)')),
                          yaxis = dict(title = dict(text='Resources Used (%)'),
                                        ticksuffix = '%'))
    pio.show(fig)



### Scatter Map Plot

if False:
    fig = go.Figure()

    #Data Creation
    d = {'Lat':np.random.randint(90,120,size),
     'Lon':np.random.randint(-180,180,size),
     'colorcode':np.random.randint(-40,20,size)}
    df = pd.DataFrame(d)

    fig.add_trace(go.Scattergeo(mode = "markers+lines",lon = df['Lon'],lat = df['Lat'],marker = {'size': 10,'color':df['colorcode'],'colorscale':'jet','colorbar_thickness':20}))
    fig.update_layout(  geo = dict(
                        showland = True,
                        showcountries = True,
                        showocean = True,
                        countrywidth = 0.5,
                        landcolor = 'rgb(230, 145, 56)',
                        lakecolor = 'rgb(0, 255, 255)',
                        oceancolor = 'rgb(0, 255, 255)',
                        projection = dict(
                            type = 'orthographic',
                        ),
                        lonaxis = dict(
                            showgrid = True,
                            gridcolor = 'rgb(102, 102, 102)',
                            gridwidth = 0.5
                        ),
                        lataxis = dict(
                            showgrid = True,
                            gridcolor = 'rgb(102, 102, 102)',
                            gridwidth = 0.5
                        )
                    )
    )
    pio.show(fig)

Edit: I intend to render these plots in a QWebEngine that will be embedded inside our PyQt5 GUIs for analysis. It is okay if I can get them to render inside a web browser for now, since we have access to Firefox, granted no internet connection.

EDIT: Semi working answer. from plotly.offline import plot

plot(fig) works for some plots. But I still have issues with Scattergeo plots as in the html it still references www.w3.org. Any suggestions for map plots?

2
Where are you running your code? An IDE? Notebook? JupyterLab?vestland
Currently just an IDE. But I will be rendering the figures in a QWebEngine in the future. We do have FireFox [and it's okay to render them there for now] with no outside network connection.Carl
Keep in mind that since version 4.0 plotly is offline only. Check thisrpanai
hi rpanai! I have seen that page and have read that text before, but I can assure you that it is not entirely true. Using same version of Plotly at work that I am at home and it works perfectly at home, and yet is trying to reach out to a website at work. I can replicate this at home by killing my internet connection as well.Carl
I believe when you import plotly you are getting the whole "enchilada"... including the parts that access plotly's servers. I don't think you need this line, if this helps I can provide a more formal answer.jayveesea

2 Answers

3
votes

The most popular way to make charts in offline mode is to use plotly's iplot function, here's an example;

from plotly.offline import iplot, init_notebook_mode
from plotly.subplots import make_subplots
init_notebook_mode()
import plotly.graph_objs as go

trace = go.Scatter(
    x=aList,
    y=aDiffList,
    name=a_name,
    mode='markers',
    marker={'color' : 'rgb(0, 0, 0)', 'size' : 6}
)
data = [trace]
layout = {'title' : 
          {'text' : '<b>Title in Bold'}, 'x' : .5,
          'font' : {'size' : 24, 'family' : 'Raleway'}
         }
iplot({'data' : data, 'layout' : layout})

I think using iplot will make your code work

1
votes

Here is the way to get this working with Maps and everything.

Create a Flask app.

import os
import sys
from flask import Flask
from flask_cors import CORS,cross_origin
import json
import argparse
from flask import session, redirect, url_for, render_template, request


app = Flask(__name__,template_folder='templates')
CORS(app)
file_dir = os.path.dirname(os.path.realpath(__file__))
    
@app.route('/plotlygeojsonfile/<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)

This should be inside a Flask folder [mine is named Flask].

In the directory Flask/plotly/topojson you need place the downloaded version of the usa_50m.json, usa_110m.json, world_50mjson, and world110m.json from http://cdn.plot.ly/{json file here} for each of the topojson files listed earlier in this sentence. Just navigate to the page and SAVE the json in that Flask/plotly/topojson folder.

Whenever you do a plotly.offline.plot(figure,config=config) call, your configure dictionary needs to at least include the following.

config = {'topojsonURL':f'http://{hostname}:{port}/plotlygeojsonfile/plotly/topojson/'}

where hostname is the hostname of the machine that the Flask app is running on and port is the port that the flask app is using.

This works for me.