Search code examples
plotlymapboxgeojson

Issues (New) When Adding Layers to Mapbox


Duplicate of question here: https://community.plotly.com/t/sudden-issues-when-adding-layers-to-mapbox/83115

Code that has worked fine for some time now (2+ years) has suddenly started throwing buggy plotly plots. I’ve tested environments and it seems to be an issue on the plotly / plotly.js side–not an environmental effect.

Plotly == 5.17 (I’ve upgraded plotly to the latest version, but the issues persist. The latest version of plotly’s corresponding plotly.js is 2.30.0, NOT 2.30.1, for what it’s worth).

The code takes a table of lat-long pairs and corresponding data and creates a group of contours in the form of MultiPolygons, then layers said contours over the mapbox.

Picture #1 is what the contours should look like.

Pictures #2-4 is what the current outcome is, via plotly, showing the layers not rendering properly.

Data to try to replicate the error can be found here: https://github.com/jkiefn1/MiscData

import pandas as pd
from datetime import datetime, date
import plotly.express as px
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata,RectSphereBivariateSpline,Rbf
import geojsoncontour
import json
import branca
import scipy as sp
import scipy.ndimage
from geojson import Feature, Polygon, dump
import geopandas as gpd
from urllib.request import urlopen
import shapely.geometry
from shapely.geometry import Point, Polygon, GeometryCollection, Polygon, mapping
from shapely.ops import unary_union
from shapely.validation import make_valid
import math

# Contours
con = [-10, -5, -2.5, -1, 0, 1, 2.5, 5, 15]

colors = ['#e6572b','#f28f38','#f2b138','#f2d338','#7eae79','#0a88ba','#0b5e9f','#0c3383','#6600FF']

data = []

df = pd.read_csv('path/to/csv/from/GitHib/data.csv')

df_cont = df.dropna().copy()

levels = con
unit = ''


vmin   = 0
vmax   = 1
cm     = branca.colormap.LinearColormap(colors, vmin=vmin, vmax=vmax).to_step(len(levels))


x_orig = (df_cont['Long'].values.tolist())
y_orig = (df_cont['Lat'].values.tolist())
z_orig = np.asarray(df_cont[month].values.tolist())


x_arr          = np.linspace(np.min(x_orig), np.max(x_orig), 1000)
y_arr          = np.linspace(np.min(y_orig), np.max(y_orig), 1000)
x_mesh, y_mesh = np.meshgrid(x_arr, y_arr)


xscale = df_cont['Long'].max() - df_cont['Long'].min()
yscale = df_cont['Lat'].max() - df_cont['Lat'].min()

scale = np.array([xscale, yscale])


z_mesh = griddata((x_orig, y_orig), z_orig, (x_mesh, y_mesh), method='linear')


sigma = [5, 5]
z_mesh = sp.ndimage.filters.gaussian_filter(z_mesh, sigma, mode='nearest')

# Create the contour
contourf = plt.contourf(x_mesh, y_mesh, z_mesh, levels, alpha=0.9, colors=colors, 
                        linestyles='none', vmin=vmin, vmax=vmax)

# Convert matplotlib contourf to geojson
geojson = geojsoncontour.contourf_to_geojson(
    contourf=contourf,
    min_angle_deg=3,
    ndigits=2,
    unit=unit,
    stroke_width=1,
    fill_opacity=0.3)

d = json.loads(geojson)
len_features=len(d['features'])
if not data:
    data.append(d)
else:
    for i in range(len(d['features'])):
         data[0]['features'].append(d['features'][i])
            
with open('path/to/any/directory/to/hold/created_geojson/temp_conditions_contour.geojson', 'w') as f:
    dump(geojson, f)

# reading in the geospatial data for the state and province boundaries
with open('path/to/the/data/from/GitHub/states_and_provinces.geojson') as f:
    states_and_provinces_json = json.load(f)

conditions_json = json.loads(geojson)

fig = px.density_mapbox(
                        df_cont,
                        lat='Lat',
                        lon='Long',
                        z=month,
                        hover_data={
                            'Code':True,
                            'Lat': True,  # remove from hover data
                            'Long': True,  # remove from hover data
                            month: True,
                        },

                        center=dict(lat=38, lon=-95), # L48 + Lower CAN
                        zoom=2.75, # L48 + Lower CAN
                        
#                         center=dict(lat=38, lon=-112), # NAM
#                         zoom=2.1, # NAM
                        
                        opacity = 0.4,
                        radius = 15,
                        mapbox_style='white-bg',
                        color_continuous_scale=['rgb(0,0,0)',
                                                'rgb(19,48,239)',
                                                'rgb(115,249,253)',
                                                'rgb(114,245,77)',
                                                'rgb(254,251,84)',
                                                'rgb(235,70,38)'],
                        range_color = [100000000, 1000000000]
                    )


# Conditions outlines
fig.update_layout(
    mapbox={
        'layers': [
            {
                'source': f,
                'line': {'width':5},
                'type':'line',
                'type':'fill',
                'color': f['properties']['fill'],
                'opacity': 1,
            }
            for f in conditions_json['features']
        ],
    }
)

# States outlines
fig.update_layout(
    mapbox={
        "layers": [
            {
                'source': g,
                'line': {"width":0.5},
                'type':"line",
                'color': 'black',
                'opacity': 1,
            }
            for g in states_and_provinces_json["features"]
        ],
    }
)

# Update the hover info and legend -- legend was replaced with image of legend
fig.update_layout(xaxis=dict(fixedrange=True),
                  yaxis=dict(fixedrange=True),

                  coloraxis_showscale=False,
)

# Update size
fig.update_layout(
    autosize=False,
    width=900,
    height=900)

fig.show()

EDIT PER THE COMMENTS

Python Version: 3.11

Plotly Version:

Name: plotly
Version: 5.17.0
Summary: An open-source, interactive data visualization library for Python
Home-page: https://plotly.com/python/
Author: Chris P
Author-email: [email protected]
License: MIT
Location: /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages
Requires: packaging, tenacity
Required-by: dash

enter image description here enter image description here enter image description here enter image description here


Solution

  • After some back-and-forth with r-beginners, I investigated the possibility of compatibility issues, and found that for whatever reason plotly5.26 and python3.11 were not playing nicely. It could be an issue unique to me alone, not sure.

    Either way, running the above OP code with python3.9.1 and plotly 5.15 worked as intended.

    Not the best solution, but a resolution nonetheless.