Sunday, 2 April 2023

Callback to apply boundary json files - plotly dash

I'm trying to assign a checklist that allows a user to visualise json boundary files. I've got a scatterplot where the user to filter unique values in Cat. I'm aiming to achieve the same output but for plotting boundary files. Also, the scatter map box should start with no boundary files until the user selects one or more.

import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objs as go
import pandas as pd
import geopandas as gpd
import json

gdf_poly = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
gdf_poly = gdf_poly.drop('name', axis = 1)

# subset African continent
Afr_gdf_area = gdf_poly[gdf_poly['continent'] == 'Africa'].reset_index(drop = True)

# subset European continent
Eur_gdf_area = gdf_poly[gdf_poly['continent'] == 'Europe'].reset_index(drop = True)

data = pd.DataFrame({
    'Cat': ['t', 'y', 'y', 'y', 'f', 'f', 'j', 'k', 'k', 'k', 's', 's', 's', 's', 'f', 'j', 'k', 'f', 'j', 'k'],
    'LAT': [5, 5, 5, 6.2, 4.3, 5.7, 14, 7, 7, 7, 7, 8.5, 19, 15, 16, 18, 17, 15, 16, 7],
    'LON': [10, 10, 10, 11.1, 9.8, 11.4, 3, 3, 3, 3, 3, 8.8, 8, 15, 8, 17, 8, 6, 16, 7],
})


external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]

app = dash.Dash(__name__, external_stylesheets = external_stylesheets, suppress_callback_exceptions = True)

app.layout = dbc.Container([
    dbc.Row([
        dbc.Col([html.Label('Cats', style = {'paddingTop': '2rem', 'display': 'inline-block'}),
                 dcc.Checklist(
                     id = 'Cats',
                     options = [
                         {'label': 't', 'value': 't'},
                         {'label': 'y', 'value': 'y'},
                         {'label': 'f', 'value': 'f'},
                         {'label': 'j', 'value': 'j'},
                         {'label': 'k', 'value': 'k'},
                         {'label': 's', 'value': 's'},
                     ],
                     value = ['t', 'y', 'f', 'j', 'k', 's'],
                 ),
                 ], 
                 width = 2),
            
                html.Label('Polygon', style = {'paddingTop': '1rem'}),
                dcc.Checklist(
                    id = 'polygons',
                    options = [
                             {'label': 'Afr', 'value': 'Afr'},
                             {'label': 'Eur', 'value': 'Eur'},                          
                             ],
                    value = ['Afr', 'Eur'],
                    #clearable=True
                ),
                 dbc.Col([
                         html.Div(dcc.Graph(id = 'chart', style = {'height':800}))
                        ], width = 5)
    ])
], fluid = True)

df = data

@app.callback(
     Output('chart', 'figure'),
    [Input("Cats", "value"),
     Input("polygons", "value"),
    ],
    )

def scatter_chart(cats, polygon):

    dff = df[df['Cat'].isin(cats)]

    data = px.scatter_mapbox(data_frame = dff,
                             lat = 'LAT',
                             lon = 'LON',
                             color = 'Cat',
                             zoom = 1,
                             mapbox_style = 'carto-positron',
                             )

    if polygon == 'Afr':
    
        data.update_layout(mapbox={
            "layers": [
                {"source": json.loads(Afr_gdf_area.geometry.to_json()),
                    "below": "traces",
                    "type": "fill",
                    "color": "orange",
                    "opacity" : 0.1,
                    "line": {"width": 1}
                },
            ],
        })    

    elif polygon == 'Eur':
    
        data.update_layout(mapbox={
            "layers": [
                {"source": json.loads(Eur_gdf_area.geometry.to_json()),
                    "below": "traces",
                    "type": "fill",
                    "color": "purple",
                    "opacity" : 0.1,
                    "line": {"width": 0.2}
                },
            ],
        })    

    else:
        pass

    fig = go.Figure(data = data)

    return fig


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


from Callback to apply boundary json files - plotly dash

No comments:

Post a Comment