#######################################################################################################################
# IMPORT LIBRARIES
#######################################################################################################################
from vois.vuetify import settings
settings.dark_mode = False
settings.color_first = '#68aad2'
settings.color_second = '#d8e7f5'
settings.button_rounded = False
import pandas as pd
from ipywidgets import widgets, Layout, HTML
from IPython.display import display
import ipyvuetify as v
from vois.vuetify import app, selectMultiple, label, datatable, toggle
import EnergyConsumption
import plotly.express as px
import plotly.graph_objects as go
#######################################################################################################################
# Define subdivision of the app content
#######################################################################################################################
#border = '1px solid lightgrey'
border = 'none'
# Dimensioning
widthinpx = 260
widthControls = '%dpx' % widthinpx
heightinpx = 830
height = '%dpx' % heightinpx
height_net = '%dpx' % (heightinpx-10)
outControls = widgets.Output(layout=Layout(width=widthControls, min_width=widthControls, height=height, border=border))
outDisplay = widgets.Output(layout=Layout(width='90%', height=height, border=border))
#######################################################################################################################
# Load data
#######################################################################################################################
g_df = EnergyConsumption.loadData()
#######################################################################################################################
# Global variables
#######################################################################################################################
g_view = 0 # Current View: 0=Chart, 1=Table, 2=Static Map, 3=Dynamic Map
g_countries = [] # Selected countries codes
g_dtfiltered = None # Filtered dataframe
g_currentgeo = '' # list of comma-separated names of the selected countries
g_sector = 'FC_E'
g_units = 'Thousand tonnes of oil equivalent'
g_year = g_df['TIME_PERIOD'].max()
# Ordered list of sectors
g_sectors = ['FC_E', 'FC_IND_E', 'FC_TRA_E', 'FC_OTH_CP_E', 'FC_OTH_HH_E']
# Short names of the sectors
g_sectorTitle = {
'FC_E': 'Total',
'FC_IND_E': 'Industrial',
'FC_TRA_E': 'Transports',
'FC_OTH_CP_E': 'Commercial',
'FC_OTH_HH_E': 'Households',
}
# Long names of the sectors
g_sectorName = {
'FC_E': 'Total energy consumption',
'FC_IND_E': 'Industrial energy consumption',
'FC_TRA_E': 'Transports energy consumption',
'FC_OTH_CP_E': 'Commercial energy consumption',
'FC_OTH_HH_E': 'Households energy consumption',
}
# Last Plotly figure
g_last_fig = None
# Color sequence to use in the Plotly chart
g_colorsequence = px.colors.sequential.Blues[::-1]
#######################################################################################################################
# Create the controls
#######################################################################################################################
# Update the filtered dataframe
def UpdateDataframe():
global g_dtfiltered, g_currentgeo
# Filter dataset on country and sector
if len(g_countries) == 0:
codes = ['EU27_2020']
g_currentgeo = 'Europe27'
else:
codes = g_countries
g_currentgeo = ', '.join([EnergyConsumption.code2name[x] for x in g_countries])
g_dtfiltered = g_df[(g_df['geo'].isin(codes))&(g_df['nrg_bal']==g_sector)].copy()
g_dtfiltered.rename({'TIME_PERIOD': 'Year', 'OBS_VALUE': g_units}, axis=1, inplace=True)
# Mapping of country name to country code. If name is None returns code for EU27
def countries_mapping(name):
if name is None:
return 'EU27_2020'
else:
return EnergyConsumption.name2code[name]
# Selection of a country
def onchange_country():
global g_countries
g_countries = selcountry.value
UpdateDataframe()
displayCurrentView()
# Selection of a sector
def onchange_sector(value):
global g_sector
g_sector = g_sectors[value]
UpdateDataframe()
displayCurrentView()
labelSector = label.label('Sector:', textweight=450, height=26)
labelEmpty = label.label('', textweight=400, height=20)
selcountry = selectMultiple.selectMultiple('Country:', EnergyConsumption.eunames, width=widthinpx-30, mapping=countries_mapping, onchange=onchange_country, marginy=2)
selsector = toggle.toggle(0, [g_sectorTitle[x] for x in g_sectors], tooltips=[g_sectorName[x] for x in g_sectors], onchange=onchange_sector, row=False, width=widthinpx-30)
outControls.clear_output()
with outControls:
display(selcountry.draw())
display(labelEmpty.draw())
display(labelSector.draw())
display(selsector.draw())
UpdateDataframe()
#######################################################################################################################
# Display filtered datatable in the outDisplay
#######################################################################################################################
def displayDatatable():
outDisplay.clear_output(wait=True)
d = datatable.datatable(data=g_dtfiltered, height=height_net)
with outDisplay:
display(d)
#######################################################################################################################
# Display Plotly Bar Chart in the outDisplay
#######################################################################################################################
def displayChart():
global g_last_fig
outDisplay.clear_output(wait=False)
with outDisplay:
title = g_sectorName[g_sector] + ' for ' + g_currentgeo
if len(g_countries) <= 1:
g_last_fig = px.bar(g_dtfiltered, x='Year', y=g_units, color="Country", template='plotly_white', text_auto=True, color_discrete_sequence=g_colorsequence)
g_last_fig.update_xaxes(tickvals=g_dtfiltered['Year'])
else:
g_last_fig = go.Figure()
i = 0
allyears = set()
for code in g_countries:
dfsel = g_dtfiltered[g_dtfiltered['geo']==code]
years = dfsel['Year'].unique()
allyears.update(years)
g_last_fig.add_trace(go.Bar(x=years, y=dfsel[g_units], name=EnergyConsumption.code2name[code], textposition="inside", texttemplate="%{y}", marker_color=g_colorsequence[i]))
i += 1
i = i % len(g_colorsequence)
g_last_fig.update_layout(barmode='group', template='plotly_white', legend_title='Country', xaxis_title="Year", yaxis_title="Thousand tonnes of oil equivalent")
g_last_fig.update_xaxes(tickvals=sorted(list(allyears)))
g_last_fig.update_layout(height=heightinpx-10, margin=dict(t=84, l=0, r=0, b=0), title={'text': title})
g_last_fig.show(config={'displaylogo': False, 'displayModeBar': False})
#######################################################################################################################
# Display the current view in the outDisplay
#######################################################################################################################
def displayCurrentView():
if g_view == 0:
displayChart()
elif g_view == 1:
displayDatatable()
elif g_view == 2:
pass
else:
pass
#######################################################################################################################
# DEFINE THE APP
#######################################################################################################################
# Click on a tab of the title: change the current view
def on_click_tab(arg):
global g_view
if arg == 'Chart':
g_view = 0
elif arg == 'Table':
g_view = 1
else:
g_app.snackbar(arg)
displayCurrentView()
# Click on the credits text
def on_click_credits():
g_app.snackbar('Credits')
# Click on the logo
def on_click_logo():
g_app.snackbar('LOGO')
# Click on the footer buttons
def on_click_footer(arg):
g_app.snackbar(arg)
g_app = app.app(title='Energy consumption example dashboard',
titlecredits='Created by Unit I.3',
titlewidth='60%',
footercolor='#dfdfe4',
footercredits='Data',
footercreditstooltip='Eurostat - European Commission',
footercreditsurl='https://ec.europa.eu/eurostat/data/database',
titletabs=['Chart', 'Table', 'Static Map', 'Dynamic Map'],
titletabsstile='font-weight: 700; font-size: 17px;',
titletabsactive=g_view,
dark=False,
backgroundimageurl='https://picsum.photos/id/293/1920/1080',
sidepaneltitle='Help',
sidepaneltext="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
sidepanelcontent=[v.Icon(class_='pa-0 ma-0 ml-2', children=['mdi-help'])],
onclicktab=on_click_tab,
onclickcredits=on_click_credits,
onclicklogo=on_click_logo,
onclickfooter=on_click_footer)
displayCurrentView()
with g_app.outcontent:
display(widgets.HBox([outControls,outDisplay]))
g_app.show()