The callback for the Scattermapbox type is problematic

Hi,

I saw the other thread is bringing up this issue and I have encountered similar issue. But I haven’t seen any solution yet.
I was trying to create the callback from a button to a Scattermapbox figure.

Every time I click that button, I want to either add or update the traces/data in the Mapbox figure but it seems the map never gets updated. The code below is an example. The dot location was supposed to keep moving as we click the button, right?

It seems from the Chrome browser log some updated data was sent to the browser but the mapbox doesn’t refresh properly to take the data. I see that the other example for other figure type may work fine but the Scattermapbox definitely has some issue. Any thought for this? Really appreciate the big help.

# -*- coding: utf-8 -*-

import os
import dash
from dash import dcc
from dash import html
import plotly.express as px
import plotly.graph_objects as go

from dash import Input, Output, State


# main entry
app = dash.Dash(__name__)
app.title = 'test app'

mapbox_token =''

fig = go.Figure( )
fig.add_trace( go.Scattermapbox(
    name='deposits_all',
    lat=[ 0 ],
    lon=[ 0 ],
    mode='markers',
    marker=go.scattermapbox.Marker(
        size=20, color='blue',
        ),
    )
    )
fig.update_layout(
    mapbox = {
        'accesstoken':mapbox_token,
        'style': "mapbox://styles/mapbox/dark-v10",
        'center': {'lon': 0, 'lat': 0 },
        'zoom': 4,
        },
    margin={"r":0,"t":0,"l":0,"b":0},
    showlegend = False,
    )


@app.callback(
    Output( 'graph_map', 'figure' ),
    inputs=dict( 
        input=Input( 'button', 'n_clicks' ), 
        fig_map=State( 'graph_map', 'figure' ),
        ),
    prevent_initial_call=True,
)
def update_loc( input, fig_map  ):
    # print( fig_map['data'] )

    # fig_map['data'][0].update( dict(
    #     lat=[ fig_map['data'][-1]['lat'][0]+1 ],
    #     lon=[ fig_map['data'][-1]['lon'][0]+1 ],
    #     marker=dict(size=20, color='blue')
    #     )
    # )

    # return fig_map

    print( fig_map['data'] )
    fig = go.Figure( )
    fig.add_trace( 
        go.Scattermapbox(
            name='deposits_all',
            lat=[ input ],
            lon=[ input ],
            mode='markers',
            marker=go.scattermapbox.Marker(
                size=20, color='blue',
                ),
            )
        )
    fig.update_layout(
        mapbox = {
            'accesstoken':mapbox_token,
            'style': "mapbox://styles/mapbox/dark-v10",
            'center': {'lon': 0, 'lat': 0 },
            'zoom': 4,
            },
        # height=600,
        margin={"r":0,"t":0,"l":0,"b":0},
        showlegend = False,
        )

    # fig = px.scatter_mapbox( lat=[ fig_map['data'][-1]['lat'][0]+1 ], lon=[ fig_map['data'][-1]['lat'][0]+1 ] )

    return fig

    

    

app.layout = html.Div( 
        [
            html.Button( 'Add', id='button' ),
            dcc.Graph( figure=fig, id='graph_map', style={'height':'500px'} ),
        ] )

if __name__ == '__main__':
    app.run_server(
        debug=True,
        dev_tools_hot_reload = True
        )

hi @candc
That is interesting. I ran your code and saw that the map actually updates the coordinates and recenters itself (I updated the code slightly); however, the original marker stays blue and in the same place. Not sure why that is yet…

The image is the result of running the app and clicking the button three times:

import os
import dash
from dash import dcc
from dash import html
import plotly.express as px
import plotly.graph_objects as go

from dash import Input, Output, State

# main entry
app = dash.Dash(__name__)
app.title = 'test app'


mapbox_token = ' '

fig = go.Figure()
fig.add_trace(go.Scattermapbox(
    name='deposits_all',
    lat=[0],
    lon=[0],
    mode='markers',
    marker=go.scattermapbox.Marker(
        size=20, color='blue',
    ),
)
)
fig.update_layout(
    mapbox={
        'accesstoken': mapbox_token,
        'style': "mapbox://styles/mapbox/dark-v10",
        'center': {'lon': 0, 'lat': 0},
        'zoom': 4,
    },
    margin={"r": 0, "t": 0, "l": 0, "b": 0},
    showlegend=False,
)


@app.callback(
    Output('graph_map', 'figure'),
    inputs=dict(
        input=Input('button', 'n_clicks'),
        fig_map=State('graph_map', 'figure'),
    ),
    prevent_initial_call=True,
)
def update_loc(input, fig_map):
    print(fig_map['data'])
    fig = go.Figure()
    fig.add_trace(
        go.Scattermapbox(
            name='deposits_all',
            lat=[input],
            lon=[input],
            mode='markers',
            marker=go.scattermapbox.Marker(
                size=80, color='blue',
            ),
        )
    )
    fig.update_layout(
        mapbox={
            'accesstoken': mapbox_token,
            'style': "mapbox://styles/mapbox/dark-v10",
            'center': {'lon': input, 'lat': input},
            'zoom': 4,
        },
        margin={"r": 0, "t": 0, "l": 0, "b": 0},
        showlegend=False,
    )


    return fig


app.layout = html.Div(
    [
        html.Button('Add', id='button'),
        dcc.Graph(figure=fig, id='graph_map', style={'height': '500px'}),
    ])

if __name__ == '__main__':
    app.run_server(
        debug=True,
        dev_tools_hot_reload=True
    )

Hi @adamschroeder. Exactly the issue I have. It seems the internal data in the map has been updated.
But the map doesn’t correctly render the updated point. The layout (the map center) was properly updated though.

This is an issue with dash 2.7, if you drop it to 2.6.2 this works as expected.

I’m wondering if it might not be an issue with the change to the newer plotly.js.

@candc – Good news - this was fixed in dash 2.7.1 :tada:

2 Likes

I tried 2.7.1 but it didnt work. Then I refreshed the page totally. LOL. And it works…

2 Likes

wow, this is good news

I did switch back to 2.6.2. It does work. Thanks so much!

glad to know! thanks a lot

1 Like