<jupyter_start><jupyter_text>EV Charging Stations Dashboard**Introduction**:This notebook demonstrates how to convert a notebook to a dashboard using Voila. The dashboard includes an analysis of EV charging station locations together with traffic data. Draw a bounding box on the map, **by using the black square on the map**, to fetch the EV charging station locations in the selected area. Select clear all to remove the content.This sample notebook will install Voila. From within the notebook, click the Voila button at the top of the notebook to easily convert the notebook to a dashboard.**Catalog**: hrn:here:data::olp-here:rib-2 **Layers**: electric-vehicle-charging-stations, topology-geometry  **Catalog**: hrn:here:data::olp-here:olp-traffic-1 **Layer**: traffic-flow<jupyter_code>##check if bqplot is installed, if not install it
import sys
import importlib.util
spec = importlib.util.find_spec('bqplot')
if spec is None:
    !{sys.executable} -m pip install bqplot
##check if voila is  installed, if not install it
import importlib.util
spec = importlib.util.find_spec('voila')
if spec is None:
    !{sys.executable} -m pip install voila
import os
from here.inspector.ipyleaflet import IpyleafletInspector
from shapely.geometry import  Point
from shapely.ops import nearest_points
from ipyleaflet import DrawControl
from ipyleaflet import Marker, Icon, Map,GeoJSON,Heatmap
from ipywidgets import Text, HTML
from ipyleaflet import WidgetControl
import ipywidgets as widgets
import pandas as pd
import geopandas
import numpy as np
import json
import geojson
import bqplot.pyplot as bq
from dashboard.evdata import EVStation, TrafficMessage, get_partition_list, nearest_messages,empty_geojson
class UI:
    def __init__(self, insp_backend, ev_control):
        self.insp_backend = insp_backend
        
        self.fig1 = bq.figure(animation_duration=750, 
                 title="Top 5 - Sum of Traffic Flow Messages/EV St. Co.", 
                 layout=widgets.Layout(flex='1 1 auto', width='auto'))
        bq.xlabel("EV St. Company Name")
        bq.ylabel("No of Nearest Messages")
        x_label = [' ',' ', ' ', ' ', ' ', ' ', ' ', ' ']
        self.line = bq.bar(x =x_label , y= [0,0,0,0,0,0,0,0])

        self.fig2 = bq.figure(title="Top 5 EV St Co.", 
                         animation_duration=750, 
                         layout=widgets.Layout(flex='1 1 auto', width='auto'))


        self.pie = bq.pie(sizes = list([0,0,0]),
                      labels =list(['','', '']),
                      display_values = True,
                      values_format=".0f",
                      display_labels='outside')
        self.pie.radius = 130
        self.pie.inner_radius = 30

        self.figures = []
        self.figures.append(self.fig1)
        self.figures.append(self.fig2)
        self.ev_control = ev_control
    
    def _display_location(self,df):
        features = []
        insert_features = lambda X: features.append(
                geojson.Feature(geometry=geojson.Point((X["longitude"],
                                                        X["latitude"]
                                                       )),
                                                    properties=dict(name=X["name"],
                                                    description=X["language"],
                                                    days=X['days_of_week_words']
                                              )))
        df.apply(insert_features, axis=1)
        ## display charging station details on the pane;
        def display_info(event, feature, **kwargs):
            html_EV_Details.value = '''
                    <h4>EV Charging Station Details</h4>
                    <b>{}</b>
                    <div>Language Code: {}</div>
                    Operating Days: {}
                '''.format(feature['properties']['name'], 
                           feature['properties']['description'],
                           feature['properties']['days'] )

        self.geo_json_layer = GeoJSON(
                            name='EV Charging Stations',
                            data=geojson.FeatureCollection(features),
                             style={'color': 'black', 'radius':5, 'fillColor': 'red', 'opacity':.7, 'weight':1.9, 'dashArray':'2', 'fillOpacity':1.0},
                             point_style={'radius': 5, 'color': 'red', 'fillOpacity': 1.0, 'fillColor': 'blue', 'weight': 3}
                       )
        self.geo_json_layer.on_click(display_info)
        insp_bkend.add_layer(self.geo_json_layer)
    
    def update_pie(self,df):
        self._display_location(df)
        grp = df.groupby(['name']).size().sort_values(ascending=False).head(5)
        self.pie.sizes = list(grp.values)
        self.pie.labels = [x.split(" ")[0] for x in list(grp.keys().values)]
        
    def update_bar(self,df):
        grp = df.groupby(['name']).size().sort_values(ascending=False).head(5)
        self.line.x =  [x.split(" ")[0] for x in list(grp.keys().values)]
        self.line.y = list(grp.values)
        self.insp_backend.add_control(self.ev_control)
        
    def update_heatmap(self, df):
        ls = []
        for index, r in df.iterrows():
            ls.append([r['geometry'].y, r['geometry'].x, r['count']*50] )
        
        self.heatmap = Heatmap(
                        name='Nearest Messages',
                        locations=ls,
                        radius=20
                    )

        self.insp_backend.add_layer(self.heatmap);
    
    def update_traffic(self, df):
        self.traffic_geo = GeoJSON(name='Traffic Flow',
                                data=df,
                                style={'color': 'blue', 'radius':1, 'fillColor': 'blue', 'opacity':1.0, 'weight':1.9, 'dashArray':'2', 'fillOpacity':1.0},
                                point_style={'radius': 1, 'color': 'blue', 'fillOpacity': 1.0, 'fillColor': 'blue', 'weight': 3}

                                )
        self.insp_backend.add_layer(self.traffic_geo)
        
    def clear_all_data(self):
        self.insp_backend.remove_layer(self.geo_json_layer)
        self.insp_backend.remove_layer(self.traffic_geo)
        self.insp_backend.remove_layer(self.heatmap)
        self.insp_backend.remove_control(self.ev_control)
        self.line.y = [0,0,0,0,0,0,0,0]
        self.pie.sizes = list([0,0,0]),
        self.pie.labels =list(['','', ''])
        html_EV_Details.value = '''
        <h4>EV Charging Station Details</h4>
        Click over an icon
    '''
        
## Event listener for rectangle on the map
def handle_draw(self, action, geo_json):
    """extract bounded rect coordinates"""   
    if action == 'created':
        global nearest_df
        global ev_df
        array = json.dumps(geo_json)
        data = json.loads(array)
        ## extract upper-left and bottom-right coordinates of bounding box
        x1 = data['geometry']['coordinates'][0][0][0]
        y1 = data['geometry']['coordinates'][0][0][1]
        x2 = data['geometry']['coordinates'][0][2][0]
        y2 = data['geometry']['coordinates'][0][2][1]
        #print(x1,y1,x2,y2)
        p_list = get_partition_list(x1,y1,x2,y2)
        ev_df = ev.get_geojson(p_list,x1,y1,x2,y2 )
        ui.update_pie(ev.data)
        geo_tr = traffic.get_geojson(p_list,x1,y1,x2,y2)
        ui.update_traffic(geo_tr)
        nearest_df = nearest_messages(ev.data, traffic.data)
        ui.update_bar(nearest_df)
        ui.update_heatmap(nearest_df)
        
    elif action == 'deleted':
        ui.clear_all_data()


##Inspector code
insp = IpyleafletInspector().set_zoom(14)
insp.set_center(Point(13.3,52.5))
insp_bkend = insp.backend()

draw_control = DrawControl(marker={},
                 rectangle={'shapeOptions': {'color': '#0000FF'}},
                 circle={},
                 polygon={},
                  polyline={},
                 circlemarker={},
                 )
draw_control.rectangle = {
    "shapeOptions": {
        "fillColor": "black",
        "color": "black",
        "fillOpacity": 0.1
    }
}
## Right side panel html
html_EV_Details = HTML('''
    <h4>EV Charging Station Details</h4>
    Click over an icon
''')
html_EV_Details.layout.margin = '0px 20px 20px 20px'
control_EV = WidgetControl(widget=html_EV_Details, position='bottomright')
##end of panel 
## instantiate all objects
ui = UI(insp_bkend, control_EV)
ev = EVStation()
traffic =  TrafficMessage()

##draw controls
draw_control.on_draw(handle_draw)
insp_bkend.add_control(draw_control)
insp.show()
display(widgets.HBox(ui.figures))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12761020881670534, 'fraction_numerical': 0.015893271461716936, 'mean_word_length': 2.2167910447761194, 'pattern_counts': {'":': 4, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '41173', 'license': 'Apache-2.0', 'n_tokens_mistral': 2657, 'n_tokens_neox': 2557, 'n_words': 557, 'path': 'tutorials/ConvertNotebook_VoilaDashboard.ipynb', 'repo_name': 'heremaps/here-data-sdk-examples-python', 'size': '8620'}