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)
No description has been provided for this image