import dash import dash_bootstrap_components as dbc import fire import pandas as pd from dash import dash_table as dt from dash import dcc from dash.dependencies import Input, Output from codecarbon.viz.components import Components from codecarbon.viz.data import Data def render_app(df: pd.DataFrame): app = dash.Dash(__name__, external_stylesheets=[dbc.themes.COSMO]) components = Components() header = components.get_header() net_summary = components.get_net_summary() project_dropdown = components.get_project_dropdown(df) project_details = components.get_project_details() exemplary_equivalents = components.get_exemplary_equivalents() _hidden_project_data = components.get_hidden_project_data() _hidden_project_summary = components.get_hidden_project_summary() cloud_emissions_comparison = components.get_cloud_emissions_comparison() global_comparison = components.get_global_comparison() regional_comparison = components.get_regional_emissions_comparison() project_time_series = components.get_project_time_series() project_emissions_bar_chart = components.get_project_emissions_bar_chart() references = components.get_references() data = Data() app.layout = dbc.Container( [ header, net_summary, project_dropdown, project_details, exemplary_equivalents, cloud_emissions_comparison, global_comparison, regional_comparison, project_time_series, project_emissions_bar_chart, references, _hidden_project_data, _hidden_project_summary, ], style={"padding-top": "50px"}, ) @app.callback( [ Output(component_id="hidden_project_data", component_property="children"), Output(component_id="hidden_project_summary", component_property="data"), Output(component_id="net_power_consumption", component_property="children"), Output(component_id="net_carbon_equivalent", component_property="children"), Output( component_id="project_infrastructure_location", component_property="children", ), Output( component_id="project_power_consumption", component_property="children" ), Output( component_id="project_carbon_equivalent", component_property="children" ), Output( component_id="last_run_power_consumption", component_property="children" ), Output( component_id="last_run_carbon_equivalent", component_property="children" ), ], [Input(component_id="project_name", component_property="value")], ) def update_project_data(project_name: str): project_data = data.get_project_data(df, project_name) project_summary = data.get_project_summary(project_data.data) net_power_consumption = f"{'{:.1f}'.format(sum(df['energy_consumed']))} kWh" net_carbon_equivalent = f"{'{:.1f}'.format(sum(df['emissions']))} kg" if {project_summary["region"]} == "": project_infrastructure_location = f"{project_summary['country_name']}" else: project_infrastructure_location = ( f"{project_summary['region']}, {project_summary['country_name']}" ) project_power_consumption = ( f"{round(project_summary['total']['energy_consumed'], 1)} kWh" ) project_carbon_equivalent = ( f"{round(project_summary['total']['emissions'], 1)} kg" ) last_run_power_consumption = ( f"{project_summary['last_run']['energy_consumed']} kWh" ) last_run_carbon_equivalent = f"{project_summary['last_run']['emissions']} kg" return ( project_data, project_summary, net_power_consumption, net_carbon_equivalent, project_infrastructure_location, project_power_consumption, project_carbon_equivalent, last_run_power_consumption, last_run_carbon_equivalent, ) @app.callback( [ Output(component_id="house_icon", component_property="src"), Output(component_id="car_icon", component_property="src"), Output(component_id="tv_icon", component_property="src"), Output(component_id="car_miles", component_property="children"), Output(component_id="tv_time", component_property="children"), Output(component_id="household_fraction", component_property="children"), ], [Input(component_id="hidden_project_summary", component_property="data")], ) def update_exemplary_equivalents(hidden_project_summary: dcc.Store): project_carbon_equivalent = hidden_project_summary["total"]["emissions"] house_icon = app.get_asset_url("house_icon.png") car_icon = app.get_asset_url("car_icon.png") tv_icon = app.get_asset_url("tv_icon.png") car_miles = f"{data.get_car_miles(project_carbon_equivalent)} miles" tv_time = data.get_tv_time(project_carbon_equivalent) household_fraction = ( f"{data.get_household_fraction(project_carbon_equivalent)} %" ) return house_icon, car_icon, tv_icon, car_miles, tv_time, household_fraction @app.callback( [ Output( component_id="global_emissions_choropleth", component_property="figure" ), Output( component_id="global_energy_mix_choropleth", component_property="figure" ), ], [ Input(component_id="hidden_project_summary", component_property="data"), Input(component_id="energy_type", component_property="value"), ], ) def update_global_comparisons(hidden_project_summary: dcc.Store, energy_type: str): net_energy_consumed = hidden_project_summary["total"]["energy_consumed"] global_emissions_choropleth_data = data.get_global_emissions_choropleth_data( net_energy_consumed ) return ( components.get_global_emissions_choropleth_figure( global_emissions_choropleth_data ), components.get_global_energy_mix_choropleth_figure( energy_type, global_emissions_choropleth_data ), ) @app.callback( Output( component_id="regional_emissions_comparison_component", component_property="style", ), [Input(component_id="hidden_project_summary", component_property="data")], ) def update_show_regional_comparison(hidden_project_summary: dcc.Store): country_iso_code = hidden_project_summary["country_iso_code"] # add country codes here to render for different countries if country_iso_code.upper() in ["USA", "CAN"]: return {"display": "block"} return {"display": "none"} @app.callback( [ Output(component_id="country_name", component_property="children"), Output( component_id="regional_emissions_comparison_choropleth", component_property="figure", ), ], [Input(component_id="hidden_project_summary", component_property="data")], ) def update_regional_comparison_choropleth(hidden_project_summary: dcc.Store): country_name = hidden_project_summary["country_name"] country_iso_code = hidden_project_summary["country_iso_code"] net_energy_consumed = hidden_project_summary["total"]["energy_consumed"] regional_emissions_choropleth_data = ( data.get_regional_emissions_choropleth_data( net_energy_consumed, country_iso_code ) ) return ( country_name, components.get_regional_emissions_choropleth_figure( regional_emissions_choropleth_data, country_iso_code ), ) @app.callback( Output(component_id="project_time_series", component_property="figure"), [Input(component_id="hidden_project_data", component_property="children")], ) def update_project_time_series(hidden_project_data: dt.DataTable): return components.get_project_time_series_figure( hidden_project_data["props"]["data"] ) @app.callback( Output(component_id="project_emissions_bar_chart", component_property="figure"), [Input(component_id="hidden_project_data", component_property="children")], ) def update_project_bar_chart(hidden_project_data: dt.DataTable): return components.get_project_emissions_bar_chart_figure( hidden_project_data["props"]["data"] ) @app.callback( Output( component_id="cloud_emissions_comparison_component", component_property="style", ), [Input(component_id="hidden_project_summary", component_property="data")], ) def update_on_cloud(hidden_project_summary: dcc.Store): on_cloud = hidden_project_summary["on_cloud"] if on_cloud == "Y": return {"display": "block"} return {"display": "none"} @app.callback( [ Output(component_id="cloud_provider_name", component_property="children"), Output( component_id="cloud_emissions_barchart", component_property="figure" ), Output(component_id="cloud_recommendation", component_property="children"), ], [Input(component_id="hidden_project_summary", component_property="data")], ) def update_cloud_emissions_barchart(hidden_project_summary: dcc.Store): on_cloud = hidden_project_summary["on_cloud"] net_energy_consumed = hidden_project_summary["total"]["energy_consumed"] cloud_provider = hidden_project_summary["cloud_provider"] cloud_region = hidden_project_summary["cloud_region"] ( cloud_provider_name, cloud_emissions_barchart_data, ) = data.get_cloud_emissions_barchart_data( net_energy_consumed, on_cloud, cloud_provider, cloud_region ) return ( cloud_provider_name, components.get_cloud_emissions_barchart_figure( cloud_emissions_barchart_data ), components.get_cloud_recommendation( on_cloud, cloud_provider_name, cloud_emissions_barchart_data ), ) return app def viz(filepath: str, port: int = 8050, debug: bool = False) -> None: df = pd.read_csv(filepath) app = render_app(df) app.run_server(port=port, debug=debug) def main(): fire.Fire(viz) if __name__ == "__main__": main()