Here is a simple recreation of my app:
app.py:
import dash
from dash import Dash, html, dcc
from flask import Flask
server = Flask(__name__)
app = Dash(name = __name__, server = server, use_pages=True)
intro_text = 'Example dash app'
app.layout = html.Div(children=[
html.Div(className = 'header_container',
children=[
html.Div(id = 'sub_header',children=[html.P(intro_text)]),
]),
html.Hr(),
html.Div(
[
html.Div(
dcc.Link(
f"{page['name']} - {page['path']}", href=page["relative_path"]
)
)
for page in dash.page_registry.values()
]
),
html.Hr(),
html.Div(className = 'page_container', children = [
dash.page_container
])
])
if __name__ == '__main__':
app.run_server(debug=True)
pages/sub_page.py:
import dash
from dash import html, dcc, Input, Output
import plotly.express as px
import random
import pandas as pd
import numpy as np
dash.register_page(__name__, path = '/')
locs = {
'Edinburgh':[],
'Leicester':[],
'Norwich':[],
'Cardiff':[],
'Aberdeen':[],
'Belfast':[],
'Execter':[],
'Liverpool':[],
'London':[]
}
locs = ['Edinburgh','Leicester','Norwich','Cardiff','Aberdeen','Belfast','Exeter','Liverpool','London']
lats = [55.923291,52.620781,52.623342,51.487850,57.154859,54.584325,50.737381,53.404520,51.524819]
lons = [-3.172652,-1.124332,1.239217,-3.177512,-2.128465,-5.934347,-3.534654,-2.965492,0.134019]
site_locs = pd.DataFrame({'SiteName':locs,'lats':lats, 'lons':lons})
fig = px.scatter_mapbox(site_locs, lat = 'lats',lon = 'lons',zoom = 5, hover_name = 'SiteName')
fig.update_layout(mapbox_style="open-street-map", margin=dict(l=0, r=0, t=0, b=0))
fig.update_layout(mapbox ={'center':{'lat':54.3,'lon':-2.2}})
fig.update_traces(marker=dict(size=12,color='darkcyan'),
selector=dict(mode='markers'))
layout = html.Div([
html.Div(className = 'main_map_page',children=[
html.Div(id = 'map_holder', children=[
dcc.Graph(id = 'location_map', figure = fig)
]),
html.Div(className = 'info_container', children = [
html.P(id = 'site_info',children = 'Site info here...'),
html.Div(id = 'co2_line'),
])
])
])
@dash.callback(Output('site_info','children'),
Output('co2_line','children'),
Input('location_map', 'clickData'))
def get_site_info(clickdata):
if clickdata:
sitename = clickdata['points'][0]['hovertext']
else:
sitename = 'Leicester'
date_range = pd.date_range('2022/01/01','2022/12/31')
num_samples = random.randint(200,300)
random_noise = np.random.uniform(-1,1,(len(date_range)))
cycle = np.sin(np.linspace(-np.pi, 0, len(date_range))) * 10
fake_data = cycle + random_noise
df = pd.DataFrame({'Data':fake_data}, index = date_range)
# Randomly sample data to represent random missing data values
df = df.sample(frac=np.random.uniform(0.6,0.7))
df.sort_index(inplace=True)
df.index.name = 'Date'
# This line seems to be the issue -
# commenting it out solves the zooming problem but the plot then fills in between the missing dates
df = df.reindex(pd.date_range(start=df.index.min(),
end=df.index.max(),
freq='1D'))
fig = px.line(df, x = df.index, y = 'Data')
line_graph = dcc.Graph(figure = fig)
return sitename, line_graph