#### Import libraries¶

In [9]:

    import time
    import matplotlib as plt
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    import bw2calc as bc
    import bw2io as bi
    import bw2data as bd
    import os
    from premise import *

#### Function to plot energy sector mixes¶

In [10]:

    import pandas as pd
    import matplotlib.pyplot as plt

    def plot_energy_contribution(region='World', sector='electricity', relative=True):
        # Load the DataFrame from the Excel file
        df = pd.read_excel('tiam-ucl_all.xlsx')

        # Define the columns to be removed
        columns_to_remove = [2005, 2010, 2015, 2020, 2060, 2070, 2080, 2090, 2100]
        columns_to_remove = [str(column) for column in columns_to_remove]

        # Remove the specified columns from the DataFrame
        df = df.drop(columns=columns_to_remove, errors='ignore')

        # Filter the DataFrame for rows where the 'Region' column matches the specified region
        df_region = df[df['Region'] == region]

        # Define energy categories and color schemes for each sector
        if sector == 'electricity':
            df_filtered = df_region[df_region['Variable'].str.startswith(('Electricity|', 'Secondary Energy|Electricity|'))]
            energy_categories = {
                'Biomass': [
                    'Secondary Energy|Electricity|Biomass combustion|w/o CCS',
                    'Secondary Energy|Electricity|Biomass existing capacity|w/o CCS',
                    'Secondary Energy|Electricity|Biomass gasification|w/o CCS',
                    'Electricity|Biogas|w/o CCS',
                    'Electricity|Biomass CHP|w/o CCS',
                    'Secondary Energy|Electricity|MSW|w/o CCS'
                ],
                'Biomass w CCS': [
                    'Secondary Energy|Electricity|Biomass combustion|w CCS',
                    'Secondary Energy|Electricity|Biomass gasification|w CCS'
                ],
                'Coal': [
                    'Secondary Energy|Electricity|CHP existing coal|w/o CCS',
                    'Secondary Energy|Electricity|Coal IGCC|w/o CCS',
                    'Secondary Energy|Electricity|Co-firing coal:biomass 50:50|w/o CCS',
                    'Secondary Energy|Electricity|Co-firing coal:biomass 80:20|w/o CCS',
                    'Secondary Energy|Electricity|Existing coal generation|w/o CCS',
                    'Secondary Energy|Electricity|Ultra-supercritical pulverised coal|w/o CCS',
                    'Secondary Energy|Electricity|Supercritical pulverised coal|w/o CCS'
                ],
                'Coal w CCS': [
                    'Secondary Energy|Electricity|Coal IGCC|w CCS',
                    'Secondary Energy|Electricity|Ultra-supercritical pulverised coal|w CCS'
                ],
                'Gas': [
                    'Secondary Energy|Electricity|Gas CCGT|w/o CCS',
                    'Secondary Energy|Electricity|Gas CHP|w/o CCS',
                    'Secondary Energy|Electricity|Gas Fuel cells|w/o CCS',
                    'Secondary Energy|Electricity|Gas turbine|w/o CCS',
                    'Secondary Energy|Electricity|Existing gas generation|w/o CCS'
                ],
                'Gas w CCS': [
                    'Secondary Energy|Electricity|Gas CCGT|w CCS'
                ],
                'Geothermal': [
                    'Secondary Energy|Electricity|Geothermal'
                ],
                'Hydro': [
                    'Secondary Energy|Electricity|Impoundment hydro',
                    'Secondary Energy|Electricity|Tidal',
                    'Secondary Energy|Electricity|ROR hydro'
                ],
                'Nuclear': [
                    'Secondary Energy|Electricity|Nuclear',
                    'Secondary Energy|Electricity|Nuclear Fusion'
                ],
                'Solar': [
                    'Secondary Energy|Electricity|Concentrated Solar CSP centralised',
                    'Secondary Energy|Electricity|Concentrated Solar PV centralised',
                    'Secondary Energy|Electricity|Concentrated Solar PV decentralised'
                ],
                'Wind': [
                    'Secondary Energy|Electricity|Offshore wind centralised',
                    'Secondary Energy|Electricity|Onshore wind centralised'
                ],
                'Oil': [
                    'Secondary Energy|Electricity|Existing oil electric generation|w/o CCS',
                    'Secondary Energy|Electricity|Oil CHP|w/o CCS',
                    'Secondary Energy|Electricity|Oil steam|w/o CCS'
                ],
                'Storage': [
                    'Secondary Energy|Electricity|Storage'
                ]
            }
            colors = {
                'Biomass': '#136729',  # Light green
                'Biomass w CCS': '#39B56B',  # Green
                'Coal': '#534A4E',  # Dark red
                'Coal w CCS': '#9A7F70',  # Lighter red
                'Gas': '#843033',  # Greyish
                'Gas w CCS': '#CA676F',  # Light greyish
                'Geothermal': '#882255',  # Darkish blue
                'Hydro': '#4C69B2',  # Blue
                'Nuclear': '#AA4499',  # Purple pinkish
                'Oil': '#878485',  # Lightest grey
                'Solar': '#F7C179',  # Yellow
                'Wind': '#51A5B2'  # Light blue
            }

        elif sector == 'steel':
            df_filtered = df_region[df_region['Variable'].str.startswith(('Production|Steel|'))]
            energy_categories = {
                'Primary, BF and BOF': [
                    'Production|Steel|Primary|BF and BOF 1|w/o CCS',
                    'Production|Steel|Primary|BF and BOF 2',
                    'Production|Steel|Primary|BF and BOF 3|w/o CCS',
                    'Production|Steel|Primary|BF and BOF 4',
                ],
                'Primary, BF and BOF w CCS': [
                    'Production|Steel|Primary|BF and BOF 1|w CCS',
                    'Production|Steel|Primary|BF and BOF 3|w CCS',
                ],
                'Secondary, DRH2 and EAF': [
                    'Production|Steel|Secondary|DRH2 and EAF',],
                'Secondary, DRI and EAF': [
                    'Production|Steel|Secondary|DRI and EAF 1',
                    'Production|Steel|Secondary|DRI and EAF 2|w/o CCS',
                    'Production|Steel|Secondary|DRI and EAF 3',
                    'Production|Steel|Secondary|DRI and EAF 2|w CCS'],
                'Secondary, EAF': [
                    'Production|Steel|Secondary|EAF 1',
                    'Production|Steel|Secondary|EAF 2',
                    'Production|Steel|Secondary|EAF 3'
                ],
            }
            colors = {
                'Primary, BF and BOF': '#843033',
                'Primary, BF and BOF w CCS': '#CA676F',
                'Secondary, DRH2 and EAF': '#51A5B2',
                'Secondary, DRI and EAF': '#AA4499',
                'Secondary, EAF': '#4C69B2'
            }

        elif sector == 'diesel':
            df_filtered = df_region[df_region['Variable'].str.contains(r'^Secondary Energy\|Liquids.*diesel', case=False, regex=True)]
            energy_categories = {
                'Synthetic': [
                    'Secondary Energy|Liquids|Biomass residues|FT Diesel|w CCS',
                    'Secondary Energy|Liquids|Biomass residues|FT Diesel|w/o CCS',
                    'Secondary Energy|Liquids|Coal|FT Diesel|w CCS',
                    'Secondary Energy|Liquids|Coal|FT Diesel|w/o CCS',
                    'Secondary Energy|Liquids|Hydrogen|Diesel',
                    'Secondary Energy|Liquids|Natural Gas|FT Diesel|w CCS',
                    'Secondary Energy|Liquids|Natural Gas|FT Diesel|w/o CCS',
                ],
                'Biomass': [
                    'Secondary Energy|Liquids|Biomass|Biodiesel|w CCS',
                    'Secondary Energy|Liquids|Biomass|Biodiesel|w/o CCS',
                ],
                'Fossil': [
                    'Secondary Energy|Liquids|Oil|Diesel',],
            }
            colors = {
                'Synthetic': '#AA4499',
                'Biomass': '#39B56B',
                'Fossil': '#843033',
            }

        elif sector == 'hydrogen':
            df_filtered = df_region[df_region['Variable'].str.startswith(('Secondary Energy|Hydrogen'))]
            energy_categories = {
                'Biomass': [
                    'Secondary Energy|Hydrogen|Biomass|w/o CCS',
                ],
                'Biomass w CCS': [
                    'Secondary Energy|Hydrogen|Biomass|w CCS',
                ],
                'Fossil': [
                    'Secondary Energy|Hydrogen|Coal|w/o CCS',
                    'Secondary Energy|Hydrogen|Natural Gas|w/o CCS'
                ],
                'Fossil w CCS': [
                    'Secondary Energy|Hydrogen|Coal|w CCS',
                ],
                'Electrolysis': [
                    'Secondary Energy|Hydrogen|Electrolysis',
                ],
            }
            colors = {
                'Biomass': '#136729',
                'Biomass w CCS': '#39B56B',
                'Fossil': '#843033',
                'Fossil w CCS': '#CA676F',
                'Electrolysis': '#4C69B2',
            }

        else:
            raise ValueError("Invalid sector specified. Choose from 'electricity', 'steel', 'diesel', or 'hydrogen'.")

        # Drop unnecessary columns
        df_filtered.drop(['Model', 'Region', 'Unit'], axis=1, inplace=True)

        # Replace 'Variable' entries according to the new categories
        for category, variables in energy_categories.items():
            df_filtered.loc[df_filtered['Variable'].isin(variables), 'Variable'] = category

        # Group by 'Scenario' and 'Variable', then sum all numerical columns
        df_grouped = df_filtered.groupby(['Scenario', 'Variable']).sum().reset_index()

        # Define scenarios and corresponding titles
        scenarios = ["SSP2-RCP60", "SSP2-RCP45", "SSP2-RCP26", "SSP2-RCP19"]
        titles = ["No climate action", "Baseline (NDCs)", "Ambitious (< 2C)", "Very ambitious (< 1.5C)"]

        # Filter the scenarios of interest
        filtered_df = df_grouped[df_grouped['Scenario'].isin(scenarios)]

        # Set the list of years to plot as x-axis values
        years = [2025, 2030, 2035, 2040, 2045, 2050]

        # Define larger font sizes for better readability
        title_fontsize = 16
        label_fontsize = 15
        legend_fontsize = 14
        tick_fontsize = 13

        # Create a figure with subplots for each scenario
        fig, axs = plt.subplots(1, len(scenarios), figsize=(12, 4), sharey=True)

        # Plot each scenario
        for idx, (scenario, title) in enumerate(zip(scenarios, titles)):
            # Filter the data for the current scenario
            scenario_data = filtered_df[filtered_df['Scenario'] == scenario]

            # Prepare the data for plotting
            labels = scenario_data['Variable'].unique()
            data_to_plot = [scenario_data[scenario_data['Variable'] == label][years].iloc[0].tolist() for label in labels if label != 'Storage']
            color_sequence = [colors[label] for label in labels if label != 'Storage']

            if relative:
                # Calculate total per year and normalize data for percentage contribution
                total_per_year = scenario_data[years].sum(axis=0)
                data_to_plot = [(data / total_per_year * 100).tolist() for data in data_to_plot]

                # Plot percentage contribution
                axs[idx].stackplot(years, data_to_plot, labels=[label for label in labels if label != 'Storage'], colors=color_sequence)
                axs[idx].set_ylabel('Percentage (%)' if idx == 0 else '', fontsize=label_fontsize)

                # Plot Storage as a line
                if 'Storage' in labels:
                    storage_data = scenario_data[scenario_data['Variable'] == 'Storage'][years].iloc[0]
                    storage_percentage = (storage_data / total_per_year * 100).tolist()
                    axs[idx].plot(years, storage_percentage, label='Storage', color='black', linewidth=2)

            else:
                # Plot actual production volume
                axs[idx].stackplot(years, data_to_plot, labels=[label for label in labels if label != 'Storage'], colors=color_sequence)
                axs[idx].set_ylabel('PJ/year' if idx == 0 else '', fontsize=label_fontsize)

                # Plot Storage as a line
                if 'Storage' in labels:
                    storage_data = scenario_data[scenario_data['Variable'] == 'Storage'][years].iloc[0]
                    axs[idx].plot(years, storage_data, label='Storage', color='black', linewidth=2)

            axs[idx].set_title(title, fontsize=title_fontsize)
            axs[idx].tick_params(axis='x', labelsize=tick_fontsize, rotation=45)
            axs[idx].tick_params(axis='y', labelsize=tick_fontsize)
            axs[idx].set_xlim(min(years), max(years))

            # Set x-ticks to show every five years
            axs[idx].set_xticks(years)
            axs[idx].set_xticklabels(years, fontsize=tick_fontsize)

        # Add a legend to the main figure
        handles, labels = axs[-1].get_legend_handles_labels()
        fig.legend(handles, labels, loc='upper right', bbox_to_anchor=(1.22, 0.95), fontsize=legend_fontsize, frameon=False)

        # Adjust layout and spacing between subplots
        plt.subplots_adjust(wspace=0.01)  # Decrease this value to reduce the space between plots
        plt.tight_layout()  # Adjust padding as needed to avoid clipping

        # Save the plot
        plt.savefig(f'{region}_{sector}.svg', format='svg', bbox_inches='tight')
        plt.show()

#### Call function and generate plots¶

You can input individual 16-regions of TIAM-UCL, and also sectors for electricity, steel, diesel, and hydrogen

In [25]:

    plot_energy_contribution(region='World', sector='electricity', relative=False) #You can switch relative to True if you want a 0-100% contribution version.

    C:\Users\js3700\AppData\Local\Temp\ipykernel_20740\1988520216.py:193: SettingWithCopyWarning:
    A value is trying to be set on a copy of a slice from a DataFrame

    See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
      df_filtered.drop(['Model', 'Region', 'Unit'], axis=1, inplace=True)