Cannot read and display local GeoJson file on MapBox

I am looking to use Dash to read in a geojson file and display it on a mapbox. As a starting point I am using this python plotly example:

https://plot.ly/python/county-level-choropleth/

which works fine. This is the code:

import dash
import plotly.graph_objs as graph_objs
import json
import dash_core_components as dcc
import dash_html_components as html

with open(‘florida-red-data.json’) as f:
data = json.load(f)

app = dash.Dash()

MAPBOX_TOKEN=MY_MAPBOX_TOKEN #<—I USE MY OWN TOKEN IN HERE

data = graph_objs.Data([
graph_objs.Scattermapbox(
lat=[‘45.5017’],
lon=[‘-73.5673’],
mode=‘markers’,
)
])
layout = graph_objs.Layout(
height=600,
autosize=True,
hovermode=‘closest’,
mapbox=dict(
layers=[
dict(
sourcetype = ‘geojson’,
source = ‘https://raw.githubusercontent.com/plotly/datasets/master/florida-red-data.json’,
#source = ‘florida-red-data.json’,
#source = data,
type = ‘fill’,
color = ‘rgba(163,22,19,0.8)’
)
],
accesstoken=(MAPBOX_TOKEN),
bearing=0,
center=dict(
lat=27.8,
lon=-83
),
pitch=0,
zoom=5.2,
style=‘light’
),
)

app.layout = html.Div([
html.Div(
html.Pre(id=‘lasso’, style={‘overflowY’: ‘scroll’, ‘height’: ‘100vh’}),
className=“three columns”
),

html.Div(
    children=dcc.Graph(id='graph',figure=dict(data =data,layout =layout))
    )

], className=“row”)

app.css.append_css({
‘external_url’: ‘https://codepen.io/chriddyp/pen/bWLwgP.css
})

if name == ‘main’:
app.run_server(debug=True)

If I save the file florida-red-data.json locally and try to access it by modifying the line

source = ‘https://raw.githubusercontent.com/plotly/datasets/master/florida-red-data.json’,

to

source = ‘.\florida-red-data.json’,

It doesn’t work.

I also tried reading in the file in at the top of the script as a global variable using:

import json
with open(‘florida-red-data.json’) as f:
data = json.load(f)

and then

source = ‘data’,

That didn’t work either. Anyone got any ideas about how I could make this work without accessing the file via a hyperlink or is this not possible? Also, if an error message is being generated is as part of this, is there a way to see it?

Have you tried source=data?

source='data' was a typo on my part. Apologies. source=data is what I used (its commented out in the code above). It produces the map but there is no sign of the geojson overlay. So do you expect that an object read in using json.load would work?

If I print data to screen after it has been loaded it appears that the file is being read successfully.

I had a similar problem trying to load local video files to a video component that i’d built. The video library worked fine standalone but baked in with Dash it couldn’t read anything local. I was only able to serve local files with a local web service. There are at least one on npm like https://www.npmjs.com/package/local-web-server

Note security issues with having this turned on and a different solution needed for production.

Still having problems with this code. @chriddyp would you expect that a local geojson file loaded with json.load would work when passed to a scattermapbox object as above?

Taking from the codepen examples shared in https://github.com/plotly/dash/issues/28, the geojson syntax is along the lines of:

geojson = {
    'type': 'FeatureCollection',
        'features': [{
            'type': 'Feature',
            'properties': {},
            'geometry': {
            'type': 'GeometryCollection',
            'geometries': [{
                'type': 'MultiPolygon',
                'coordinates': [
                    [[
                        [-73, 45],
                        [-76, 46],
                        [-75, 47],
                        [-73, 45]
                    ]],
                    [[
                        [-70, 42],
                        [-73, 43],
                        [-72, 44],
                        [-70, 42]
                    ]]        
                ]
            }]
        }
    }]
}

figure = {
    'data': [{
        type: 'scattermapbox',
        lat: [46],
        lon: [-74]
    }],
    'layout': {
        'mapbox': {
            'accesstoken': your_mapbox_access_token
            'layers': [

                {
                    'sourcetype': 'geojson',
                    'source': geojson,
                    'type': 'fill',

                    'color': 'rgba(30, 30, 30, 0.5)'
                },
                
                {
                    'sourcetype': 'geojson',
                    'source': geojson,
                    'type': 'line',

                    'color': 'blue',
                    'line': {
                        'width': 2
                    }
                },
                
                {
                    'sourcetype': 'geojson',
                    'source': geojson,
                    'type': 'circle',

                    'color': 'red',
                    'circle': {
                        'radius': 6
                    }
                }
            ]
        }    
    }
}

Turns out there was a pretty basic (they don’t come much more basic) error in my code. I loaded in my geojosn file into a variable called ‘data’ and then reused ‘data’ as the output of the graph_objs.Data function.

Used a different variable name and it works now.

1 Like

Hey @chriddyp,

I have a similar issue on a Dash app Im developping. Basically I get the first display of the data right and a map pops up with the data I expect to observe. However the map doesnt respond to changes. So I see the map with the initial data inserted but when I change options, colors or legends it doesnt work.

Here is the code with an excerpt of geojson. Do you know why?

@app.callback(
Output(‘county-choropleth’, ‘figure’),

[dash.dependencies.Input(‘button-1’, ‘n_clicks’)],
state=[
State(‘opacity-slider’, ‘value’),
State(‘colorscale-picker’, ‘colorscale’),
State(‘hide-map-legend’, ‘values’),
State(‘county-choropleth’, ‘figure’)])
def display_map(nclick,opacity, colorscale, map_checklist, figure):
cm = dict(zip(BINS, colorscale))
df_2015=pd.read_csv(‘df.csv’)
df_2015.coordinates=df_2015.coordinates.apply(lambda x: ast.literal_eval(x))
data = [dict(
lat = df_lat_lon['Latitude '],
lon = df_lat_lon[‘Longitude’],
text = df_lat_lon[‘Hover’],
type = ‘scattermapbox’,
hoverinfo = ‘text’,
marker = dict(size=5, color=‘white’, opacity=0)
)]

annotations = [dict(
showarrow = False,
align = ‘right’,
text = ‘’,
x = 0.95,
y = 0.95,
)]

for i, bin in enumerate(reversed(BINS)):
color = cm[bin]
annotations.append(
dict(
arrowcolor = color,
text = bin,
x = 0.95,
y = 0.85-(i/20),
ax = -60,
ay = 0,
arrowwidth = 5,
arrowhead = 0,
bgcolor = ‘#EFEFEE
)
)

if ‘hide_legend’ in map_checklist:
annotations = []

if ‘layout’ in figure:
lat = figure[‘layout’][‘mapbox’][‘center’][‘lat’]
lon = figure[‘layout’][‘mapbox’][‘center’][‘lon’]
zoom = figure[‘layout’][‘mapbox’][‘zoom’]
else:
lat = 38.72490,
lon = -95.61446,
zoom = 2.5

layout = dict(
mapbox = dict(
layers = [],
accesstoken = mapbox_access_token,
style = ‘light’,
center=dict(lat=lat, lon=lon),
zoom=zoom
),
hovermode = ‘closest’,
margin = dict(r=0, l=0, t=0, b=0),
annotations = annotations,
dragmode = ‘lasso’
)

for i,bin in enumerate(BINS):
df=df_2015.loc[int(i*len(df_2015)/len(BINS)):int((i+1)*len(df_2015)/len(BINS))].reset_index()
l={“type”: “FeatureCollection”,
“crs”: { “type”: “name”, “properties”: { “name”: “urn:ogc:def:crs:OGC:1.3:CRS84” } },‘features’:df[‘coordinates’].tolist()}
geo_layer = dict(
sourcetype = ‘geojson’,
source = l,
type = ‘fill’,
color = cm[bin],
opacity = opacity
)
layout[‘mapbox’][‘layers’].append(geo_layer)

fig = dict(data=data, layout=layout)
return fig
Here is a part of the geojson
{‘crs’: {‘properties’: {‘name’: ‘urn:ogc:def:crs:OGC:1.3:CRS84’},
‘type’: ‘name’},
‘features’: [{‘geometry’: {‘coordinates’: [[[-100.093183, 35.181919],
[-100.000075, 35.181919],
[-100.000075, 35.028564],
[-100.000075, 34.743763],
[-100.416322, 34.74924],
[-100.542292, 34.74924],
[-100.536815, 35.181919],
[-100.093183, 35.181919]]],
‘type’: ‘Polygon’},
‘properties’: {‘County’: ‘Collingsworth County,TX’,
‘FIPS’: ‘48087’,
‘FIPS State’: 48,
‘ST’: ‘TX’,
‘State’: ‘Texas’,
‘id’: ‘48087’,
‘name’: ‘Collingsworth’},
‘type’: ‘Feature’},
{‘geometry’: {‘coordinates’: [[[[-84.286733, 32.750157],
[-84.204579, 32.689911],
[-84.001932, 32.531079],
[-84.051224, 32.520126],
[-84.253871, 32.372248],
[-84.36341, 32.399633],
[-84.390795, 32.416064],
[-84.445564, 32.563941],
[-84.286733, 32.750157]]],
[[[-84.051224, 32.520126],
[-84.007409, 32.520126],
[-84.018363, 32.503695],
[-84.051224, 32.520126],
[-84.051224, 32.520126]]]],
‘type’: ‘MultiPolygon’},
‘properties’: {‘County’: ‘Taylor County,GA’,
‘FIPS’: ‘13269’,
‘FIPS State’: 13,
‘ST’: ‘GA’,
‘State’: ‘Georgia’,
‘id’: ‘13269’,
‘name’: ‘Taylor’},
‘type’: ‘Feature’}}

1 Like

I had the exactly same problem. Did you solve it at the end? Local still not working I have to upload the geojson to somewhere to url instead.

I had the original problem where I would download the JSON file from github, store it locally, and then provide the local path as the source value without success (map would draw, but no data would be overlayed on the map). My solution was to use json.load() to convert the JSON file to Python data structures, then pass that to the Layout class constructor:

with open('./datasets/florida-red-data.json') as f:
    red_data = json.load(f)
with open('./datasets/florida-blue-data.json') as f:
    blue_data = json.load(f)

layout = graph_objs.Layout(
    height=600,
    autosize=True,
    hovermode='closest',
    mapbox=dict(
        layers=[
            dict(
                sourcetype='geojson',
                # source='https://raw.githubusercontent.com/plotly/datasets/master/florida-red-data.json',
                source=red_data,
                type='fill',
                color='rgba(163,22,19,0.8)'
            ),
            dict(
                sourcetype='geojson',
                # source='https://raw.githubusercontent.com/plotly/datasets/master/florida-blue-data.json',
                source=blue_data,
                type='fill',
                color='rgba(40,0,113,0.8)'
            )
        ],
        accesstoken=mapbox_access_token,
1 Like

Brand new first-class geojson choropleths are now available in Dash 1.1.1 :tada: Many thanks to the organization that sponsored this feature :heart: (more about how to sponsor & fund our open source work: https://plot.ly/products/consulting-and-oem).
Resources:

1 Like

Hi everyone!

in one of the examples above it use just one geojson.
Is it possible to load more than one geojson file?

Thanks.

1 Like