コード例 #1
0
def render_page():
    cols = []
    edf = predict_emissions().dropna(axis=1, how='all')
    forecast = edf.pop('Forecast')
    graph = PredictionFigure(sector_name=None,
                             unit_name='kt',
                             title='Päästöt yhteensä',
                             smoothing=True,
                             fill=True,
                             stacked=True,
                             legend=True,
                             legend_x=0.8)
    for sector_name, sector_metadata in SECTORS.items():
        df = pd.DataFrame(edf[sector_name])
        df['Forecast'] = forecast

        fig = make_sector_fig(df, sector_name, sector_metadata)
        sector_page = get_page_for_emission_sector(sector_name, None)
        card = GraphCard(id='emissions-%s' % sector_name,
                         graph=dict(figure=fig),
                         link_to_page=sector_page)
        cols.append(dbc.Col(card.render(), md=6))

        # Add the summed sector to the all emissions graph
        df = df.drop(columns=['Forecast'])
        s = df.sum(axis=1)
        s.name = 'Emissions'
        df = pd.DataFrame(s)
        df['Forecast'] = forecast
        graph.add_series(df=df,
                         trace_name=sector_metadata['name'],
                         column_name='Emissions',
                         historical_color=sector_metadata['color'])

    target_year = get_variable('target_year')
    ref_year = get_variable('ghg_reductions_reference_year')
    perc_off = get_variable('ghg_reductions_percentage_in_target_year')

    last_hist_year = edf.loc[~forecast].index.max()
    last_hist = edf.loc[last_hist_year].sum()
    end_emissions = edf.loc[target_year].sum()
    ref_emissions = edf.loc[ref_year].sum()
    target_emissions = ref_emissions * (1 - perc_off / 100)

    target_year_emissions = edf.loc[target_year].sum()
    sticky = StickyBar(
        label='Päästövähennykset yhteensä',
        goal=last_hist - target_emissions,
        value=last_hist - end_emissions,
        unit='kt',
        below_goal_good=False,
    )

    card = GraphCard(id='emissions-total',
                     graph=dict(figure=graph.get_figure()))

    return html.Div(
        [dbc.Row(dbc.Col(card.render())),
         dbc.Row(cols),
         sticky.render()])
コード例 #2
0
def generate_solar_power_stacked(df):
    pv_kwh_wp = get_variable('yearly_pv_energy_production_kwh_wp')
    df.SolarPowerNew = df.SolarPowerNew * pv_kwh_wp
    df.SolarPowerExisting = df.SolarPowerExisting * pv_kwh_wp
    df.loc[~df.Forecast, 'SolarPowerNew'] = np.nan

    graph = PredictionFigure(sector_name='ElectricityConsumption',
                             unit_name='GWh',
                             title='Aurinkopaneelien sähköntuotanto',
                             stacked=True,
                             fill=True,
                             color_scale=2)
    graph.add_series(df=df,
                     trace_name='Vanhat rakennukset',
                     column_name='SolarPowerExisting',
                     color_idx=0)
    graph.add_series(df=df,
                     trace_name='Uudet rakennukset',
                     column_name='SolarPowerNew',
                     color_idx=1)

    forecast_df = df[df.Forecast]
    hist_df = df[~df.Forecast]
    years_left = forecast_df.index.max() - hist_df.index.max()
    ekwpa = (forecast_df.SolarPowerExisting.iloc[-1] -
             hist_df.SolarPowerExisting.iloc[-1]) / years_left
    nkwpa = forecast_df.SolarPowerNew.iloc[-1] / years_left

    return graph.get_figure(), ekwpa / pv_kwh_wp, nkwpa / pv_kwh_wp
コード例 #3
0
    def get_content(self):
        lang = get_active_locale()
        main_sector_name = self.emission_sector[0]
        main_sector_metadata = SECTORS[main_sector_name]

        cols = []

        edf = predict_emissions().dropna(axis=1, how='all')
        forecast = edf.pop('Forecast')
        edf = edf[main_sector_name]

        subsectors = main_sector_metadata['subsectors']
        colors = generate_color_scale(main_sector_metadata['color'],
                                      len(subsectors))

        graph = PredictionFigure(sector_name=main_sector_name,
                                 unit_name='kt',
                                 title=_('Total emissions'),
                                 smoothing=True,
                                 fill=True,
                                 stacked=True,
                                 legend=True,
                                 legend_x=0.8)

        for idx, (sector_name,
                  sector_metadata) in enumerate(subsectors.items()):
            df = pd.DataFrame(edf[sector_name])
            df['Forecast'] = forecast

            fig = self.make_sector_fig(df, sector_name, sector_metadata,
                                       colors[idx])
            sector_page = get_page_for_emission_sector(main_sector_name,
                                                       sector_name)
            card = GraphCard(id='emissions-%s-%s' %
                             (main_sector_name, sector_name),
                             graph=dict(figure=fig),
                             link_to_page=sector_page)
            cols.append(dbc.Col(card.render(), md=6))

            # Add the summed sector to the all emissions graph
            df = df.drop(columns=['Forecast'])
            s = df.sum(axis=1)
            s.name = 'Emissions'
            df = pd.DataFrame(s)
            df['Forecast'] = forecast
            graph.add_series(df=df,
                             trace_name=sector_metadata.get(
                                 'name_%s' % lang, sector_metadata['name']),
                             column_name='Emissions',
                             historical_color=colors[idx])

        self.total_emissions = edf.iloc[-1].sum()

        card = GraphCard(id='%s-emissions-total' % main_sector_name,
                         graph=dict(figure=graph.get_figure()))

        return html.Div([
            dbc.Row(dbc.Col(card.render())),
            dbc.Row(cols),
        ])
コード例 #4
0
def make_sector_fig(df, name, metadata):
    fig = PredictionFigure(
        sector_name=name,
        unit_name='kt',
        title=metadata['name'],
        smoothing=True,
        # allow_nonconsecutive_years=True,
        fill=True,
        stacked=True,
    )
    if len(df.columns) == 2:
        fig.add_series(df=df, trace_name='Päästöt', column_name='')
    else:
        fig.legend = True
        fig.legend_x = 0.8
        column_names = list(df.columns)
        column_names.remove('Forecast')
        colors = generate_color_scale(metadata['color'], len(column_names))
        for idx, col_name in enumerate(column_names):
            subsector = metadata['subsectors'][col_name]
            fig.add_series(df=df,
                           trace_name=subsector['name'],
                           column_name=col_name,
                           historical_color=colors[idx])
    return fig.get_figure()
コード例 #5
0
 def make_sector_fig(self, df, name, metadata, base_color):
     lang = get_active_locale()
     fig = PredictionFigure(
         sector_name=name,
         unit_name='kt',
         title=metadata.get('name_%s' % lang, metadata['name']),
         smoothing=True,
         # allow_nonconsecutive_years=True,
         fill=True,
         stacked=True,
     )
     if len(df.columns) == 2:
         fig.add_series(df=df,
                        trace_name=_('Emissions'),
                        column_name='',
                        historical_color=base_color)
     else:
         fig.legend = True
         fig.legend_x = 0.8
         column_names = list(df.columns)
         column_names.remove('Forecast')
         colors = generate_color_scale(base_color, len(column_names))
         for idx, col_name in enumerate(column_names):
             subsector = metadata['subsectors'][col_name]
             fig.add_series(df=df,
                            trace_name=subsector.get(
                                'name_%s' % lang, metadata['name']),
                            column_name=col_name,
                            historical_color=colors[idx])
     return fig.get_figure()
コード例 #6
0
def draw_district_heat_consumption_emissions(df):
    graph = PredictionFigure(
        sector_name='BuildingHeating',
        unit_name='kt',
        title='Kaukolämmön kulutuksen päästöt',
        smoothing=True,
        allow_nonconsecutive_years=True,
        fill=True,
    )
    graph.add_series(df=df, column_name='NetEmissions', trace_name='Päästöt')
    return graph.get_figure()
コード例 #7
0
def draw_new_building_unit_heat_factor_graph(df):
    graph = PredictionFigure(
        sector_name='BuildingHeating',
        unit_name='kWh/k-m²',
        title=_('Future building stock heat efficiency'),
        color_scale=2,
    )
    graph.add_series(df=df,
                     column_name='NewBuildingHeatUsePerNetArea',
                     trace_name=_('Heat efficiency'),
                     color_idx=1)
    return graph.get_figure()
コード例 #8
0
def draw_new_building_unit_heat_factor_graph(df):
    graph = PredictionFigure(
        sector_name='BuildingHeating',
        unit_name='kWh/k-m²',
        title='Uuden rakennuskannan ominaislämmönkulutus',
        color_scale=2,
    )
    graph.add_series(df=df,
                     column_name='NewBuildingHeatUsePerNetArea',
                     trace_name='Ominaislämmönkulutus',
                     color_idx=1)
    return graph.get_figure()
コード例 #9
0
def generate_district_heating_emission_factor_graph(df):
    graph = PredictionFigure(
        sector_name='BuildingHeating',
        unit_name='g/kWh',
        title='Kaukolämmön päästökerroin',
        smoothing=True,
        allow_nonconsecutive_years=True,
    )
    graph.add_series(
        df=df,
        column_name='Emission factor',
        trace_name='Päästökerroin',
    )

    return graph.get_figure()
コード例 #10
0
def generate_district_heating_forecast_graph(df):
    graph = PredictionFigure(
        sector_name='BuildingHeating',
        unit_name='kt/vuosi',
        title='Kaukolämmön kulutuksen päästöt',
        smoothing=True,
        allow_nonconsecutive_years=True,
        fill=True,
    )
    graph.add_series(
        df=df,
        column_name='District heat consumption emissions',
        trace_name='Päästöt',
    )

    return graph.get_figure()
コード例 #11
0
def generate_solar_power_graph(df, label, col, ymax, is_existing):
    graph = PredictionFigure(
        sector_name='ElectricityConsumption',
        unit_name='MWp',
        title='%s rakennuskannan aurinkopaneelien piikkiteho' % label,
        y_max=ymax,
        color_scale=2)
    if is_existing:
        color_idx = 0
    else:
        color_idx = 1

    graph.add_series(df=df,
                     trace_name='Piikkiteho',
                     column_name=col,
                     color_idx=color_idx)
    return graph.get_figure()
コード例 #12
0
def draw_bev_chart(df):
    engines = {'electric', 'gasoline', 'diesel'}
    df = df.dropna()[[*engines, 'Forecast']].copy()
    graph = PredictionFigure(
        sector_name='Transportation',
        unit_name='%',
        title='Sähköautojen ajosuoriteosuus',
        legend=True,
        legend_x=0.6,
        y_max=100,
    )

    for col in engines:
        et = ENGINE_TYPES[col]
        df[col] *= 100
        graph.add_series(
            df=df, column_name=col, trace_name=et['name'], historical_color=et['color']
        )

    return graph.get_figure()
コード例 #13
0
def draw_heat_consumption(df):
    df.loc[~df.Forecast, 'NewBuildingHeatUse'] = np.nan
    graph = PredictionFigure(
        title=_('District heat net consumption'),
        unit_name='GWh',
        sector_name='BuildingHeating',
        smoothing=True,
        stacked=True,
        fill=True,
        color_scale=2,
    )

    graph.add_series(
        df=df,
        column_name='ExistingBuildingHeatUse',
        trace_name=_('Existing buildings'),
        color_idx=0,
    )
    graph.add_series(df=df,
                     column_name='NewBuildingHeatUse',
                     trace_name=_('Future buildings'),
                     color_idx=1)

    return graph.get_figure()
コード例 #14
0
def draw_heat_consumption(df):
    df.loc[~df.Forecast, 'NewBuildingHeatUse'] = np.nan
    graph = PredictionFigure(
        title='Kaukolämmön kokonaiskulutus',
        unit_name='GWh',
        sector_name='BuildingHeating',
        smoothing=True,
        stacked=True,
        fill=True,
        color_scale=2,
    )

    graph.add_series(
        df=df,
        column_name='ExistingBuildingHeatUse',
        trace_name='Vanhat rakennukset',
        color_idx=0,
    )
    graph.add_series(df=df,
                     column_name='NewBuildingHeatUse',
                     trace_name='Uudet rakennukset',
                     color_idx=1)

    return graph.get_figure()
コード例 #15
0
def solar_power_callback(existing_building_perc, new_building_perc):
    # First see what the maximum solar production capacity is to set the
    # Y axis maximum.
    set_variable('solar_power_existing_buildings_percentage', 100)
    set_variable('solar_power_new_buildings_percentage', 100)
    kwp_max = predict_solar_power_production()

    # Then predict with the given percentages.
    set_variable('solar_power_existing_buildings_percentage',
                 existing_building_perc)
    set_variable('solar_power_new_buildings_percentage', new_building_perc)
    kwp_df = predict_solar_power_production()

    ymax = kwp_max.SolarPowerExisting.iloc[-1]
    fig_old = generate_solar_power_graph(kwp_df, "Vanhan",
                                         "SolarPowerExisting", ymax, True)
    # ymax = kwp_max.SolarPowerNew.iloc[-1]
    fig_new = generate_solar_power_graph(kwp_df, "Uuden", "SolarPowerNew",
                                         ymax, False)
    fig_tot, ekwpa, nkwpa = generate_solar_power_stacked(kwp_df)

    graph = PredictionFigure(sector_name='ElectricityConsumption',
                             unit_name='kt',
                             title='Aurinkopaneelien päästövaikutukset',
                             fill=True)
    ef_df = predict_electricity_emission_factor()
    kwp_df['NetEmissions'] = -kwp_df['SolarProduction'] * ef_df[
        'EmissionFactor'] / 1000
    graph.add_series(df=kwp_df,
                     column_name='NetEmissions',
                     trace_name='Päästövaikutukset')
    fig_emissions = graph.get_figure()

    s = kwp_df.SolarProduction

    cd = CardDescription()

    city_owned = get_variable('building_area_owned_by_org') / 100
    cd.set_values(existing_building_perc=existing_building_perc,
                  org_existing_building_kwp=1000 * ekwpa * city_owned,
                  others_existing_building_kwp=1000 * ekwpa * (1 - city_owned))

    existing_kwpa = cd.render("""
    Kun aurinkopaneeleita rakennetaan {existing_building_perc:noround} % kaikesta vanhan
    rakennuskannan kattopotentiaalista, {org_genitive} tulee rakentaa aurinkopaneeleita
    {org_existing_building_kwp} kWp vuodessa skenaarion toteutumiseksi. Muiden kuin {org_genitive}
    tulee rakentaa {others_existing_building_kwp} kWp aurinkopaneeleita vuodessa.
    """)

    cd.set_values(new_building_perc=new_building_perc,
                  org_new_building_kwp=1000 * nkwpa * city_owned,
                  others_new_building_kwp=1000 * nkwpa * (1 - city_owned))
    new_kwpa = cd.render("""
    Kun uuteen rakennuskantaan rakennetaan aurinkopaneeleja {new_building_perc:noround} %
    kaikesta kattopotentiaalista, {org_genitive} tulee rakentaa aurinkopaneeleja
    {org_new_building_kwp} kWp vuodessa skenaarion toteutumiseksi. Muiden kuin {org_genitive}
    tulee rakentaa {others_new_building_kwp} kWp aurinkopaneeleita vuodessa.
    """)

    forecast = s.iloc[-1] * get_variable('yearly_pv_energy_production_kwh_wp')

    sticky = StickyBar(
        label='Aurinkosähkön tuotanto',
        value=forecast,
        unit='GWh',
        current_page=page,
    )

    return [
        fig_old, fig_new, fig_tot, fig_emissions, existing_kwpa, new_kwpa,
        sticky.render()
    ]
コード例 #16
0
def cars_callback(bev_percentage, mileage_adj):
    set_variable('cars_bev_percentage', bev_percentage)
    set_variable('cars_mileage_per_resident_adjustment', mileage_adj)

    df = predict_cars_emissions()
    df['Mileage'] /= 1000000

    bev_chart = draw_bev_chart(df)
    """
    graph = PredictionFigure(
        sector_name='Transportation',
        unit_name='%',
        title='Biopolttoaineiden osuus myydyissä polttoaineissa',
    )
    graph.add_series(
        df=df, column_name='electric', trace_name='Bion osuus'
    )
    biofuel_chart = graph.get_figure()
    """

    graph = PredictionFigure(
        sector_name='Transportation',
        unit_name='km/as.',
        title='Ajokilometrit asukasta kohti',
    )
    graph.add_series(
        df=df, column_name='PerResident', trace_name='Suorite/as.',
    )
    per_resident_chart = graph.get_figure()

    # Total mileage
    graph = PredictionFigure(
        sector_name='Transportation',
        unit_name='milj. km',
        title='%s ajetut henkilöautokilometrit' % get_variable('municipality_locative'),
        fill=True,
    )
    graph.add_series(
        df=df, column_name='Mileage', trace_name='Ajosuorite',
    )
    mileage_chart = graph.get_figure()

    # Total emissions
    graph = PredictionFigure(
        sector_name='Transportation',
        unit_name='g/km',
        title='Henkilöautojen päästökerroin',
    )
    graph.add_series(
        df=df, column_name='EmissionFactor', trace_name='Päästökerroin',
    )
    emission_factor_chart = graph.get_figure()

    # Total emissions
    graph = PredictionFigure(
        sector_name='Transportation',
        unit_name='kt (CO₂e.)',
        title='Henkilöautoilun päästöt',
        fill=True,
    )
    graph.add_series(
        df=df, column_name='Emissions', trace_name='Päästöt',
    )
    emissions_chart = graph.get_figure()

    cd = CardDescription()
    first_forecast = df[df.Forecast].iloc[0]
    last_forecast = df[df.Forecast].iloc[-1]
    last_history = df[~df.Forecast].iloc[-1]

    cd.set_values(
        bev_percentage=get_variable('cars_bev_percentage'),
        bev_mileage=last_forecast.Mileage * last_forecast.electric,
        per_resident_adjustment=get_variable('cars_mileage_per_resident_adjustment'),
        target_population=last_forecast.Population,
    )
    bev_desc = cd.render("""
        Skenaariossa polttomoottorihenkilöautot korvautuvat sähköautoilla siten,
        että vuonna {target_year} {municipality_genitive} kaduilla ja teillä
        ajetaan sähköautoilla {bev_percentage:noround} % kaikista ajokilometreistä
        ({bev_mileage} milj. km).
    """)
    pr_desc = cd.render("""
        Vuonna {target_year} {municipality_locative} asuu {target_population} ihmistä.
        Skenaariossa ajokilometrit asukasta kohti muuttuvat vuoteen {target_year} mennessä
        {per_resident_adjustment:noround} %.
    """)

    sticky = make_bottom_bar(df)

    return [
        bev_chart, dbc.Col(bev_desc), emission_factor_chart,
        per_resident_chart, dbc.Col(pr_desc), mileage_chart,
        emissions_chart, sticky
    ]
コード例 #17
0
def electricity_consumption_callback(value):
    set_variable('electricity_consumption_per_capita_adjustment', value / 10)

    df = predict_electricity_consumption_emissions()

    graph = PredictionFigure(sector_name='ElectricityConsumption',
                             title=_('Electricity consumption per resident'),
                             unit_name='kWh/as.')
    graph.add_series(df=df,
                     trace_name=_('Consumption/res.'),
                     column_name='ElectricityConsumptionPerCapita')
    per_capita_fig = graph.get_figure()

    graph = PredictionFigure(
        sector_name='ElectricityConsumption',
        title=_('Electricity consumption'),
        unit_name='GWh',
        fill=True,
    )
    graph.add_series(df=df,
                     trace_name=_('Electricity consumption'),
                     column_name='NetConsumption')
    consumption_fig = graph.get_figure()

    graph = PredictionFigure(
        sector_name='ElectricityConsumption',
        title=_('Electricity production emission factor'),
        unit_name='g/kWh',
        smoothing=True,
    )
    graph.add_series(df=df,
                     trace_name=_('Emission factor'),
                     column_name='EmissionFactor')
    factor_fig = graph.get_figure()

    graph = PredictionFigure(
        sector_name='ElectricityConsumption',
        title=_('Electricity consumption emissions'),
        unit_name='kt',
        smoothing=True,
        fill=True,
    )
    graph.add_series(df=df, trace_name='Päästöt', column_name='NetEmissions')
    emission_fig = graph.get_figure()

    graph = PredictionFigure(
        sector_name='ElectricityConsumption',
        title=_('Local PV production'),
        unit_name='GWh',
        smoothing=True,
        fill=True,
    )
    graph.add_series(df=df,
                     trace_name='Tuotanto',
                     column_name='SolarProduction')
    solar_fig = graph.get_figure()

    first_forecast = df[df.Forecast].iloc[0]
    last_forecast = df[df.Forecast].iloc[-1]
    last_history = df[~df.Forecast].iloc[-1]
    last_history_year = df[~df.Forecast].index.max()

    cd = CardDescription()
    cd.set_values(
        per_resident_adj=get_variable(
            'electricity_consumption_per_capita_adjustment'),
        per_resident_change=(
            (last_forecast.ElectricityConsumptionPerCapita /
             last_history.ElectricityConsumptionPerCapita) - 1) * 100,
        last_history_year=last_history.name,
        solar_production_target=last_forecast.SolarProduction,
        solar_production_perc=(last_forecast.SolarProduction * 100) /
        last_forecast.ElectricityConsumption,
        solar_production_hist=last_history.SolarProduction,
    )
    per_resident_desc = cd.render("""
        Skenaariossa asukaskohtainen sähkönkulutus pienenee {per_resident_adj:noround} % vuodessa.
        Vuonna {target_year} asukaskohtainen kulutus on muuttunut {per_resident_change} % nykyhetkestä.
    """)
    solar_desc = cd.render("""
        Vuonna {target_year} {municipality_locative} sijaitsevilla aurinkopaneeleilla
        tuotetaan {solar_production_target} GWh, joka on {solar_production_perc} %
        kaikesta vuoden {target_year} kulutussähköstä.
    """)

    bar = StickyBar(label=_('Electicity consumption emissions'),
                    value=last_forecast.NetEmissions,
                    unit='kt',
                    current_page=page)

    return [
        per_capita_fig,
        dbc.Col(per_resident_desc, style=dict(minHeight='6rem')), solar_fig,
        dbc.Col(solar_desc, style=dict(minHeight='6rem')), consumption_fig,
        factor_fig, emission_fig,
        bar.render()
    ]
コード例 #18
0
def district_heating_consumption_callback(existing_building_perc,
                                          new_building_perc):
    set_variable('district_heating_existing_building_efficiency_change',
                 existing_building_perc / 10)
    set_variable('district_heating_new_building_efficiency_change',
                 new_building_perc / 10)

    df = predict_district_heat_consumption()
    geo_df = predict_geothermal_production()
    geo_df = geo_df[geo_df.Forecast]
    df['GeoEnergyProductionExisting'] = geo_df['GeoEnergyProductionExisting']
    df['GeoEnergyProductionNew'] = geo_df['GeoEnergyProductionNew']

    df['ExistingBuildingHeatUse'] -= df['GeoEnergyProductionExisting'].fillna(
        0)
    df['NewBuildingHeatUse'] -= df['GeoEnergyProductionNew'].fillna(0)

    first_forecast = df[df.Forecast].iloc[0]
    last_forecast = df[df.Forecast].iloc[-1]
    last_history = df[~df.Forecast].iloc[-1]

    cd = CardDescription()
    org_owned = get_variable('building_area_owned_by_org') / 100
    geo_production = last_forecast.GeoEnergyProductionExisting + last_forecast.GeoEnergyProductionNew
    cd.set_values(
        existing_renovation=get_variable(
            'district_heating_existing_building_efficiency_change'),
        new_improvement=get_variable(
            'district_heating_new_building_efficiency_change'),
        existing_next_year_reduction=(1 -
                                      (first_forecast.ExistingBuildingHeatUse -
                                       last_history.ExistingBuildingHeatUse)) *
        org_owned,
        new_area=last_forecast.NewBuildingNetArea,
        existing_area=last_forecast.ExistingBuildingNetArea,
        geo_production=geo_production,
        geo_percentage=(geo_production / last_forecast.TotalHeatConsumption) *
        100,
    )
    existing_desc = cd.render("""
        Skenaarion mukaan nykyistä rakennuskantaa remontoidaan siten, että rakennuksien
        energiatehokkuus paranee {existing_renovation:noround} % vuodessa. Ensi vuonna {org_genitive}
        omistamien rakennuksien lämmönkulutuksen pitää pudota {existing_next_year_reduction} GWh.
    """)
    new_desc = cd.render("""
        Uuden rakennuskannan energiatehokkuus paranee skenaariossa {new_improvement:noround} % vuodessa.
        Vuonna {target_year} nykyistä rakennuskantaa on {existing_area} milj. kem² ja uutta rakennuskantaa
        {new_area} milj. kem².
    """)
    geo_desc = cd.render("""
        Vanhassa ja uudessa rakennuskannassa korvataan kaukolämpöä paikallisesti tuotetulla
        maalämmöllä siten, että vuonna {target_year} kaukolämpöä korvataan {geo_production} GWh
        ({geo_percentage} % sen vuoden kaukolämmönkulutuksesta).
    """)

    fig1 = draw_existing_building_unit_heat_factor_graph(df)
    fig2 = draw_new_building_unit_heat_factor_graph(df)

    geo_fig = PredictionFigure(
        sector_name='BuildingHeating',
        unit_name='GWh',
        title='Maalämmöllä korvattu kaukolämpö',
        fill=True,
    )
    geo_fig.add_series(
        df=geo_df,
        column_name='GeoEnergyProduction',
        trace_name='Maalämpötuotanto',
    )

    fig3 = draw_heat_consumption(df)

    df = predict_district_heating_emissions()
    unit_emissions_card = make_unit_emissions_card(df)
    fig4 = draw_district_heat_consumption_emissions(df)
    sticky = make_bottom_bar(df)

    return [
        fig1,
        dbc.Col(existing_desc, style=dict(minHeight='8rem')), fig2,
        dbc.Col(new_desc, style=dict(minHeight='8rem')),
        geo_fig.get_figure(),
        dbc.Col(geo_desc, style=dict(minHeight='8rem')), fig3,
        unit_emissions_card, fig4, sticky
    ]