diff --git a/AUTHORS.md b/AUTHORS.md
new file mode 100644
index 0000000..6659f8b
--- /dev/null
+++ b/AUTHORS.md
@@ -0,0 +1,91 @@
+# Authors
+
+## Authorship of the notebooks
+
+All notebooks were created
+by [Daniel Huppmann](https://www.iiasa.ac.at/staff/huppmann)
+([@danielhuppmann](https://github.com/danielhuppmann))
+in close collaboration with the authors of Chapter 2
+of the **IPCC Special Report on Global Warming of 1.5°C**
+([Rogelj, Shindell, Jiang, et al., 2018](http://www.ipcc.ch/report/sr15/)).
+
+Joeri Rogelj, Elmar Kriegler, Luis Mundaca, Piers Forster, Shigeki Kobayashi,
+Roland Séférian, María Virginia Vilariño and other authors of the SR15
+contributed to the methodology of the assessment and development of figures
+and tables generated by the notebooks.
+
+## Authorship of the scenario ensemble
+
+### Guidelines for authorship of the scenario ensemble
+
+The IAMC Steering Committee agreed on the following rules to decide
+on the list of authors for the scenario resource:
+
+1) the group of people involved in the collection, vetting,
+ and review of the scenario data,
+2) all first authors of the studies that submitted scenarios to the ensemble,
+3) in case that modelling teams have a limited number of first-authors,
+ it is possible to nominate additional authors. In this case, each team can
+ nominate one author per study that they contributed to,
+ up to a maximum of three authors (ie, under point (2) and (3) each team
+ is eligible to a total number of three authors, unless more than three
+ first-author studies were submitted by the team).
+
+### List of authors
+
+Group of authors involved in the collection, vetting,
+and review of scenario data (see guidelines, item 1):
+
+- Daniel Huppmann (SR1.5 Chapter 2 author, coordination, review & vetting,
+ technical implementation and data transfer)
+- Elmar Kriegler (SR1.5 Chapter 2 author, vetting & review)
+- Volker Krey (technical implementation and data transfer)
+- Keywan Riahi (SR1.5 Chapter 5 author, review, project lead)
+- Joeri Rogelj (SR1.5 Chapter 2 author, vetting & review)
+- Steven Rose (major contributions to the IAMC-IPCC coordination and the MoU)
+- John Weyant (major contributions to the IAMC-IPCC coordination and the MoU)
+
+Authors representing modelling teams that submitted scenarios
+to the ensemble (see guidelines, items 2 and 3):
+
+- Nico Bauer *(REMIND-MAgPIE, Bauer et al., forthcoming)*
+- Christoph Bertram *(REMIND-MAgPIE, Bertram et al., 2018)*
+- Valentina Bosetti *(WITCH, nominated per guidelines item 3)*
+- Katherine Calvin *(GCAM, nominated per guidelines item 3)*
+- Jonathan Doelman *(IMAGE, nominated per guidelines item 3)*
+- Laurent Drouet *(WITCH, nominated per guidelines item 3)*
+- Johannes Emmerling *(WITCH, nominated per guidelines item 3)*
+- Stefan Frank *(MESSAGEix-GLOBIOM, nominated per guidelines item 3)*
+- Shinichiro Fujimori *(AIM, nominated per guidelines item 3)*
+- David Gernaat *(IMAGE, nominated per guidelines item 3)*
+- Arnulf Grubler *(MESSAGEix-GLOBIOM, Grubler et al., 2018)*
+- Céline Guivarch *(IMACLIM, nominated per guidelines item 3)*
+- Martin Haigh *(Shell, Shell International B.V., 2018)*
+- Christian Holz *(C-ROADS, Holz et al., 2018)*
+- Gokul Iyer *(GCAM, nominated per guidelines item 3)*
+- Etsushi Kato *(GRAPE, nominated per guidelines item 3)*
+- Kimon Keramidas *(POLES, nominated per guidelines item 3)*
+- Alban Kitous *(POLES, nominated per guidelines item 3)*
+- Florian Leblanc *(IMACLIM, nominated per guidelines item 3)*
+- Jing-Yu Liu *(AIM, Liu et al., 2018)*
+- Konstantin Löffler *(GENeSYSMOD, Löffler et al., 2017)*
+- Gunnar Luderer *(REMIND-MAgPIE, Luderer et al., 2018)*
+- Adriana Marcucci *(MERGE-ETL, Marcucci et al., 2017)*
+- David McCollum *(MESSAGEix-GLOBIOM, McCollum et al., 2018)*
+- Silvana Mima *(POLES, nominated per guidelines item 3)*
+- Alexander Popp *(REMIND-MAgPIE, nominated per guidelines item 2)*
+- Ronald D. Sands *(FARM, nominated per guidelines item 3)*
+- Fuminori Sano *(DNE21+, nominated per guidelines item 3)*
+- Jessica Strefler *(REMIND-MAgPIE, Strefler et al., 2018)*
+- Junichi Tsutsui *(BET, nominated per guidelines item 3)*
+- Detlef van Vuuren *(IMAGE, Van Vuuren et al., 2018)*
+- Zoi Vrontisi *(GEM-E3, Vrontisi et al., 2018)*
+- Marshall Wise *(GCAM, nominated per guidelines item 3)*
+- Runsen Zhang *(AIM, Zhang et al., 2018)*
+
+## Acknowledgements
+
+The authors wish to thank Peter Kolp for the technical support in the
+compilation and data management of the scenario ensemble.
+Nikolay Kushin and Michael Pimmer are acknowledged for their contribution to
+the development of the scenario explorer and the database infrastructure.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..308b386
--- /dev/null
+++ b/README.md
@@ -0,0 +1,114 @@
+# Scenario analysis notebooks
for the *IPCC Special Report on Global Warming of 1.5°C*
+
+## License
+
+Copyright 2018 IIASA
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+## Overview
+
+The notebooks included in this repository implement the categorisation of
+scenarios by climate impact and generate figures, tables, summary statistics,
+and assessment indicators used in the **IPCC Special Report on Global Warming
+of 1.5°C** ([SR15](http://www.ipcc.ch/report/sr15/)).
+
+See [analysis/README](analysis/README.md) for an overview of notebooks
+and the cross-references to figures, tables and assessment in the SR15.
+
+A rendered version of this repository and the notebooks are available at
+[data.ene.iiasa.ac.at/sr15_scenario_analysis](https://data.ene.iiasa.ac.at/sr15_scenario_analysis).
+
+## Tricklebacks and corrections
+
+Due to changes of focus or groupings of scenarios in some assessments
+during the approval plenary of the IPCC, the SPM and chapters
+are still subject to minor changes and updates (i.e., tricklebacks)
+as well as correction of editorial errors until the final publication
+of the Special Report. For this reason, the outputs of notebooks included in
+this repository may deviate from the pre-release version of the SR1.5.
+
+An updated version of the notebooks will be released following the
+publication of the final, copy-edited version of the SR1.5
+
+## Scenario ensemble download
+
+The scenario ensemble used for this assessment is available for download
+at [data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer).
+
+The scenario data is licensed under a derivative of the Creative Commons CC-BY 4.0 License.
+If appropriate reference is made to the data source, it is permitted to use
+the data for scientific research and science communication.
+However, redistribution of substantial portions of the data is restricted.
+
+Please read the guidelines and legal code
+at [data.ene.iiasa.ac.at/iamc-1.5c-explorer/#/license](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer/#/license)
+before redistributing this data or adapted material.
+
+When using the scenario data for any analysis, figures or tables,
+please clearly state the release version of the scenario ensemble.
+
+## Scientific references
+
+For the **scientific assessment of the Special Report**, please cite:
+> Joeri Rogelj, Drew Shindell, Kejun Jiang,
+> Solomone Fifita, Piers Forster, Veronika Ginzburg, Collins Handa,
+> Haroon Kheshgi, Shigeki Kobayashi, Elmar Kriegler, Luis Mundaca,
+> Roland Séférian, and Maria Virginia Vilariño.
+> *Mitigation pathways compatible with 1.5°C
+> in the context of sustainable development*,
+> in "Special Report on Global Warming of 1.5°C (SR15)".
+> Intergovernmental Panel on Climate Change: Geneva, 2018.
+> url: [www.ipcc.ch/report/sr15/](https://www.ipcc.ch/report/sr15/)
+
+For a **high-level description of the scenario ensemble**, please refer to:
+> Daniel Huppmann, Joeri Rogelj, Elmar Kriegler, Volker Krey, and Keywan Riahi.
+> A new scenario resource for integrated 1.5 °C research.
+> *Nature Climate Change*, 2018.
+> doi: [10.1038/s41558-018-0317-4](https://doi.org/10.1038/s41558-018-0317-4)
+
+When using the **scenario ensemble data** for own analysis, please cite:
+> Daniel Huppmann, Elmar Kriegler, Volker Krey, Keywan Riahi, Joeri Rogelj,
+> Steven K. Rose, John Weyant, et al.,
+> *IAMC 1.5°C Scenario Explorer and Data hosted by IIASA*.
+> Integrated Assessment Modeling Consortium & International Institute for Applied Systems Analysis, 2018.
+> doi: [10.22022/SR15/08-2018.15429](https://doi.org/10.22022/SR15/08-2018.15429) |
+> url: [data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)
+
+For the **Jupyter notebooks containing figure plotting and analysis scripts**
+included in this repository, please cite:
+> Daniel Huppmann et al.,
+> *Scenario analysis notebooks for the IPCC Special Report on Global Warming of 1.5°C*. 2018.
+> doi: [10.22022/SR15/08-2018.15428](https://doi.org/10.22022/SR15/08-2018.15428) |
+> url: [github.com/iiasa/ipcc_sr15_scenario_analysis](https://github.com/iiasa/ipcc_sr15_scenario_analysis)
+
+Please refer to the [AUTHORS](AUTHORS.md) document for the full list of authors
+of the scenario ensemble and the notebooks in this repository.
+
+You can download these citations and the references
+for all studies that submitted scenarios to the ensemble
+as [Endnote (enl)](bibliography/iamc_1.5c_scenario_data.enl),
+[Reference Manager (ris)](bibliography/iamc_1.5c_scenario_data.ris),
+and [BibTex (bib)](bibliography/iamc_1.5c_scenario_data.bib) format.
+
+## Dependencies
+
+The notebooks included in this repository depend on the *pyam* package,
+an open-source Python package for IAM scenario analysis and visualization
+developed by Matthew Gidden ([@gidden](https://github.com/gidden))
+and Daniel Huppmann ([@danielhuppmann](https://github.com/danielhuppmann/)).
+
+See [software.ene.iiasa.ac.at/pyam/](https://software.ene.iiasa.ac.at/pyam/)
+for installation instructions and the full documentation of *pyam*.
+The source code is available at [github.com/IAMconsortium/pyam](https://github.com/IAMconsortium/pyam).
+
diff --git a/_static/IAMC_logo.jpg b/_static/IAMC_logo.jpg
new file mode 100644
index 0000000..a2341a3
Binary files /dev/null and b/_static/IAMC_logo.jpg differ
diff --git a/assessment/README.md b/assessment/README.md
new file mode 100644
index 0000000..4f22108
--- /dev/null
+++ b/assessment/README.md
@@ -0,0 +1,83 @@
+# Overview of figures, tables and statistics generated from the notebooks
+
+ - Notebook `sr15_2.0_categories_indicators`
+ - Validation of scenario data
+ - Categorisation by climate impact and warming trajectory
+ including **Table 2.1**
+ - Assignment of illustrative pathway archetypes
+ - Computation of metadata indicators
+
+ - Notebook `spm_sr15_statements`
+ - Summary statistics and indicators
+ derived from the scenario assessment
+ highlighted in the *Summary for Policy Makers*
+
+ - Notebook `spm_sr15_figure_3a_global_emissions_pathways`
+ - Data tables of emissions pathways
+ for **Summary for Policymakers (SPM), Figure 3a**
+
+ - Notebook `spm_sr15_figure_3b_illustrative_pathways`
+ - Diagnostic indicators of illustrative pathways
+ for **Summary for Policymakers (SPM), Figure 3b**
+
+ - Notebook `sr15_2.3.1_range_of_assumptions`
+ - **Figure 2.4**: Range of assumptions about socio-economic drivers and
+ projections for energy and food demand in the pathways available
+ for this assessment.
+
+ - Notebook `sr15_2.3.3_global_emissions_characteristics`
+ - **Figure 2.6**: Annual global emissions characteristics
+ for 2020, 2030, 2050 and 2100.
+
+ - Notebook `sr15_2.3.3_global_emissions_statistics`
+ - **Table 2.4** Annual global emissions and absolute annual rates of change
+
+ - Notebook `sr15_2.3.3_short-lived_climate_forcers`
+ - **Figure 2.7**: Global characteristics of a selection of short-lived
+ non-CO2 emissions until mid-century.
+
+ - Notebook `sr15_2.3.3_short-lived_climate_forcers_radiative_forcing`
+ - **Figure 2.8**: Estimated aggregated effective radiative forcing of SLCFs
+ for 1.5°C and 2°C pathway classes in 2010, 2030, 2050, and 2100,
+ as estimated by the FAIR model (Smith et al., 2018).
+
+ - Notebook `sr1p5_2.3.4_carbon_dioxide_removal`
+ - **Figure 2.9**: Cumulative deployment of carbon dioxide removal (CDR)
+ in 1.5°C-consistent pathways
+
+ - Notebook `sr15_2.4.1_final_energy`
+ - **Figure 2.14**: Decomposition of transformation pathways by energy demand,
+ carbon intensity of electricity, the electricity share in final energy,
+ and the carbon intensity of the residual (non-electricity) fuel mix
+
+ - Notebook `sr15_2.4.2.1_primary_energy_marker-scenarios`
+ - **Figure 2.15**: Primary energy supply for the four illustrative pathway
+ archetypes and the IEA’s Faster Transition Scenario, and their relative
+ location in the ranges for 1.5°C and 2°C pathways
+
+ - Notebook `sr15_2.4.2.1_primary_energy_statistics`
+ - **Table 2.6**: Descriptive statistics of global primary energy supply
+
+ - Notebook `sr15_2.4.2.2_electricity_generation_marker-scenarios`
+ - **Figure 2.16**: Electricity generation for the four illustrative pathway
+ archetypes and the IEA’s Faster Transition Scenario, and their relative
+ location in the ranges for 1.5°C and 2°C pathways
+
+ - Notebook `sr15_2.4.2.2_electricity_generation_statistics`
+ - **Table 2.7**: Descriptive statistics of electricity generation by fuel
+
+ - Notebook `sr15_2.4.2.3_ccs_deployment`
+ - **Figure 2.17**: CCS deployment in 1.5°C and 2°C pathways for biomass, coal
+ and natural gas, and the cumulative quantity of carbon dioxide stored
+
+ - Notebook `sr15_2.4.4_afolu_emissions`
+ - **Figure 2.25**: Agricultural non-CO2 emissions in 1.5°C pathways
+
+ - Notebook `sr15_2.5_carbon_price_analysis`
+ - **Figure 2.26**: Global price of carbon emissions
+ consistent with mitigation pathways grouped by warming category
+ - Assessment of relative carbon prices between pairs
+ of 1.5°C vs. 2°C pathways
+
+ - Notebook `sr15_4.2_sectoral_indicators`
+ - **Table 4.1**: Sectoral indicators of the pace of transformation
diff --git a/assessment/output/README.md b/assessment/output/README.md
new file mode 100644
index 0000000..5eadd16
--- /dev/null
+++ b/assessment/output/README.md
@@ -0,0 +1,3 @@
+# Output folder
+
+This is the folder for output including tables and figures generated as part of the assessment for the IPCC SR1.5.
\ No newline at end of file
diff --git a/assessment/spm_sr15_figure_3a_global_emissions_pathways.ipynb b/assessment/spm_sr15_figure_3a_global_emissions_pathways.ipynb
new file mode 100644
index 0000000..31e8d7b
--- /dev/null
+++ b/assessment/spm_sr15_figure_3a_global_emissions_pathways.ipynb
@@ -0,0 +1,276 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Global emission pathway characteristics\n",
+ "\n",
+ "## Figure 3a of the *Summary for Policymakers*\n",
+ "\n",
+ "This notebook extracts the emissions pathways for Figure 3a in the Summary for Policymakers\n",
+ "of the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "cats = specs.pop('cats')\n",
+ "cats_15 = specs.pop('cats_15')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment\n",
+ "\n",
+ "This figure only includes scenarios where the 2010 Kyoto GHG emissions are in line with the valid range as determined by the Second Assessment Report."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.meta.rename(columns={'Kyoto-GHG|2010 (SAR)': 'kyoto_ghg_2010'}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats_15, kyoto_ghg_2010='in range')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for filters and initialize data list"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=df, category=cats, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = []"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plot different emissions pathways by category"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "writer = pd.ExcelWriter('output/spm_sr15_figure3a_data_table.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2 = (\n",
+ " df.filter(variable='Emissions|CO2')\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")\n",
+ "\n",
+ "pyam.utils.write_sheet(writer, 'Net CO2',\n",
+ " pyam.filter_by_meta(co2, **filter_args), index=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ch4 = df.filter(variable='Emissions|CH4').timeseries()\n",
+ "pyam.utils.write_sheet(writer, 'CH4',\n",
+ " pyam.filter_by_meta(ch4, **filter_args), index=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bc = df.filter(variable='Emissions|BC')\n",
+ "pyam.utils.write_sheet(writer, 'Black carbon',\n",
+ " pyam.filter_by_meta(bc.timeseries(), **filter_args), index=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "n2o = df.filter(variable='Emissions|N2O').timeseries()\n",
+ "pyam.utils.write_sheet(writer, 'N2O',\n",
+ " pyam.filter_by_meta(n2o, **filter_args), index=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fgases = df.filter(variable='Emissions|F-Gases').timeseries()\n",
+ "pyam.utils.write_sheet(writer, 'F-Gases',\n",
+ " pyam.filter_by_meta(fgases, **filter_args), index=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "so2 = df.filter(variable='Emissions|Sulfur').timeseries()\n",
+ "pyam.utils.write_sheet(writer, 'Sulfur',\n",
+ " pyam.filter_by_meta(so2, **filter_args), index=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Save timeseries data to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "writer.save()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [default]",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/spm_sr15_figure_3b_illustrative_pathways.ipynb b/assessment/spm_sr15_figure_3b_illustrative_pathways.ipynb
new file mode 100644
index 0000000..301671f
--- /dev/null
+++ b/assessment/spm_sr15_figure_3b_illustrative_pathways.ipynb
@@ -0,0 +1,478 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Characteristics of four illustrative model pathways\n",
+ "## Figure 3b of the *Summary for Policymakers*\n",
+ "\n",
+ "This notebook derives the indicators for the table in Figure 3b in the Summary for Policymakers\n",
+ "of the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats_15 = specs.pop('cats_15')\n",
+ "cats_15_no_lo = specs.pop('cats_15_no_lo')\n",
+ "marker = specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.meta.rename(columns={'Kyoto-GHG|2010 (SAR)': 'kyoto_ghg_2010'}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats_15)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "base_year = 2010\n",
+ "compare_years = [2030, 2050]\n",
+ "years = [base_year] + compare_years"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Initialize a `pyam.Statistics` instance"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats = pyam.Statistics(df=df, groupby={'marker': ['LED', 'S1', 'S2', 'S5']},\n",
+ " filters=[(('pathways', 'no & lo os 1.5'), {'category': cats_15_no_lo})])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Collecting indicators\n",
+ "\n",
+ "### CO2 and Kyoto GHG emissions reductions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2 = (\n",
+ " df.filter(variable='Emissions|CO2', year=years)\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for y in compare_years:\n",
+ " stats.add((co2[y] / co2[2010] - 1) * 100,\n",
+ " 'CO2 emission reduction (% relative to 2010)',\n",
+ " subheader=y)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "kyoto_ghg = (\n",
+ " df.filter(variable='Emissions|Kyoto Gases (SAR-GWP100)', year=years)\n",
+ " .convert_unit({'Mt CO2-equiv/yr': ('Gt CO2-equiv/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")\n",
+ "for y in compare_years:\n",
+ " stats.add((kyoto_ghg[y] / kyoto_ghg[base_year] - 1) * 100,\n",
+ " 'Kyoto-GHG emission reduction (SAR-GWP100), % relative to {})'.format(base_year),\n",
+ " subheader=y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Final energy demand reduction relative to 2010"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fe = df.filter(variable='Final Energy', year=years).timeseries()\n",
+ "for y in compare_years:\n",
+ " stats.add((fe[y] / fe[base_year] - 1) * 100,\n",
+ " 'Final energy demand reduction relative to {} (%)'.format(base_year),\n",
+ " subheader=y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Share of renewables in electricity generation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def add_stats_share(stats, var_list, name, total, total_name, years, df=df):\n",
+ "\n",
+ " _df = df.filter(variable=var_list)\n",
+ " for v in var_list:\n",
+ " _df.require_variable(v, exclude_on_fail=True)\n",
+ " _df.filter(exclude=False, inplace=True)\n",
+ "\n",
+ " component = (\n",
+ " _df.timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ " )\n",
+ " share = component / total * 100\n",
+ " \n",
+ " for y in years:\n",
+ " stats.add(share[y], header='Share of {} in {} (%)'.format(name, total_name),\n",
+ " subheader=y)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ele = df.filter(variable='Secondary Energy|Electricity', year=compare_years).timeseries()\n",
+ "ele.index = ele.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ele_re_vars = [\n",
+ " 'Secondary Energy|Electricity|Biomass',\n",
+ " 'Secondary Energy|Electricity|Non-Biomass Renewables'\n",
+ "]\n",
+ "add_stats_share(stats, ele_re_vars, 'renewables', ele, 'electricity', compare_years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Changes in primary energy mix"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mapping = [\n",
+ " ('coal', 'Coal'),\n",
+ " ('oil', 'Oil'),\n",
+ " ('gas', 'Gas'),\n",
+ " ('nuclear', 'Nuclear'),\n",
+ " ('bioenergy', 'Biomass'),\n",
+ " ('non-biomass renewables', 'Non-Biomass Renewables')\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for (n, v) in mapping:\n",
+ " data = df.filter(variable='Primary Energy|{}'.format(v), year=years).timeseries()\n",
+ "\n",
+ " for y in compare_years:\n",
+ " stats.add((data[y] / data[base_year] - 1) * 100,\n",
+ " header='Primary energy from {} (% rel to {})'.format(n, base_year),\n",
+ " subheader=y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Cumulative carbon capture and sequestration until the end of the century"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def cumulative_ccs(variable, name, first_year=2016, last_year=2100):\n",
+ "\n",
+ " data = (\n",
+ " df.filter(variable=variable)\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ " )\n",
+ " \n",
+ " stats.add(\n",
+ " data.apply(pyam.cumulative, raw=False, axis=1,\n",
+ " first_year=first_year, last_year=last_year),\n",
+ " header='Cumulative {} until {} (GtCO2)'.format(name, last_year), subheader='')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cumulative_ccs('Carbon Sequestration|CCS', 'CCS')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cumulative_ccs('Carbon Sequestration|CCS|Biomass', 'BECCS')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Land cover for energy crops"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "energy_crops = df.filter(variable='Land Cover|Cropland|Energy Crops', year=2050).timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats.add(energy_crops[2050], header='Land are for energy crops (MHa)')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Emissions from land use"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "species = ['CH4', 'N2O']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for n in species:\n",
+ " data = df.filter(variable='Emissions|{}|AFOLU'.format(n), year=years).timeseries()\n",
+ "\n",
+ " for y in compare_years:\n",
+ " stats.add((data[y] / data[base_year] - 1) * 100,\n",
+ " header='Agricultural {} emissions (% rel to {})'.format(n, base_year),\n",
+ " subheader=y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Display summary statistics and export to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "summary = stats.summarize(interquartile=True, custom_format='{:.0f}').T\n",
+ "summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "NameError",
+ "evalue": "name 'summary' is not defined",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0msummary\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto_excel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'output/spm_sr15_figure3b_indicators_table.xlsx'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[0;31mNameError\u001b[0m: name 'summary' is not defined"
+ ]
+ }
+ ],
+ "source": [
+ "summary.to_excel('output/spm_sr15_figure3b_indicators_table.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [default]",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/spm_sr15_statements.ipynb b/assessment/spm_sr15_statements.ipynb
new file mode 100644
index 0000000..de113af
--- /dev/null
+++ b/assessment/spm_sr15_statements.ipynb
@@ -0,0 +1,703 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Statements of the *Summary for Policymakers*
derived from the scenario assessment\n",
+ "\n",
+ "This notebook computes the summary statistics highlighted in the Summary for Policymakers\n",
+ "of the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "cats = specs.pop('cats')\n",
+ "cats_15 = specs.pop('cats_15')\n",
+ "cats_15_no_lo = specs.pop('cats_15_no_lo')\n",
+ "cats_2 = specs.pop('cats_2')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "compare_year = 2010"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.meta.rename(columns={'Kyoto-GHG|2010 (SAR)': 'kyoto_ghg_2010'}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Define filters for `pyam.Statistics` instance"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filters_15_no_lo = [('no & lo os 1.5', {'category': cats_15_no_lo})]\n",
+ "filters_compare = filters_15_no_lo + [('2.0', {'category': cats_2})]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statement C1: Net CO2 emissions by warming categories and year of crossing the net-zero threshold"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c1 = pyam.Statistics(df=df, filters=filters_compare, rows=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2 = df.filter(kyoto_ghg_2010='in range', variable='Emissions|CO2')\n",
+ "co2.convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)}, inplace=True)\n",
+ "co2 = co2.timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for y in [2030]:\n",
+ " stats_c1.add((1 - co2[y] / co2[compare_year]) * 100,\n",
+ " header='Reduction in emissions by {}'.format(y),\n",
+ " subheader='relative to {} (%)'.format(compare_year),\n",
+ " row='Net CO2 emissions')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Only include scenarios in this statistic that reach net-zero CO2 emissions before the end of the century"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "net_zero = df.filter(kyoto_ghg_2010='in range').meta['year of netzero CO2 emissions']\n",
+ "netzero = net_zero[net_zero < 2100]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c1.add(netzero,\n",
+ " header='Year of net-zero'.format(y),\n",
+ " subheader=''.format(compare_year),\n",
+ " row='Net CO2 emissions')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c1.summarize(center='median', interquartile=True, custom_format='{:.0f}')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statement C1.2: Reductions of methane and black carbon"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c12 = pyam.Statistics(df=df, filters=filters_15_no_lo, rows=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ch4 = df.filter(kyoto_ghg_2010='in range', variable='Emissions|CH4').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for y in [2050]:\n",
+ " stats_c12.add((1 - ch4[y] / ch4[compare_year]) * 100,\n",
+ " header='Reduction in emissions by {}'.format(y),\n",
+ " subheader='relative to {} (%)'.format(compare_year),\n",
+ " row='Methane (CH4)')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bc = df.filter(variable='Emissions|BC').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for y in [2050]:\n",
+ " stats_c12.add((1 - bc[y] / bc[compare_year]) * 100,\n",
+ " header='Reduction in emissions by {}'.format(y),\n",
+ " subheader='relative to {} (%)'.format(compare_year),\n",
+ " row='Black carbon')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c12.summarize(center='mean', fullrange=True, custom_format='{:.0f}')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statement C2.2: Energy system transformation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def add_stats_share(stats, var_list, name, total, total_name, years, df=df):\n",
+ "\n",
+ " _df = df.filter(variable=var_list)\n",
+ " for v in var_list:\n",
+ " _df.require_variable(v, exclude_on_fail=True)\n",
+ " _df.filter(exclude=False, inplace=True)\n",
+ "\n",
+ " component = (\n",
+ " _df.timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ " )\n",
+ " share = component / total * 100\n",
+ " \n",
+ " for y in years:\n",
+ " stats.add(share[y], header='Share of {} in {}'.format(total_name, y),\n",
+ " subheader='(%)', row=name)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c22 = pyam.Statistics(df=df, filters=filters_15_no_lo, rows=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ele = df.filter(variable='Secondary Energy|Electricity').timeseries()\n",
+ "ele.index = ele.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ele_re_vars = [\n",
+ " 'Secondary Energy|Electricity|Biomass',\n",
+ " 'Secondary Energy|Electricity|Non-Biomass Renewables'\n",
+ "]\n",
+ "\n",
+ "add_stats_share(stats_c22, ele_re_vars, 'renewables', ele, 'electricity generation', [2050])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ele_gas = ['Secondary Energy|Electricity|Gas']\n",
+ "add_stats_share(stats_c22, ele_gas, 'natural gas', ele, 'electricity generation', [2050])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ele_coal = ['Secondary Energy|Electricity|Coal']\n",
+ "add_stats_share(stats_c22, ele_coal, 'coal', ele, 'electricity generation', [2050])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c22.summarize(center='mean', interquartile=True, custom_format='{:.0f}')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statement C2.3: CO2 emissions from industry"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c23 = pyam.Statistics(df=df, filters=filters_compare)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_ind = df.filter(variable='Emissions|CO2|Energy|Demand|Industry').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for y in [2050]:\n",
+ " stats_c23.add((1 - co2_ind[y] / co2_ind[compare_year]) * 100,\n",
+ " header='Industrial emissions reductions relative to {} (%)'.format(compare_year),\n",
+ " subheader=y)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c23.summarize(center='median', interquartile=True, custom_format='{:.0f}')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statement C2.4: Urban infrastructure and transport"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c24 = pyam.Statistics(df=df, filters=filters_compare, rows=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bld = df.filter(variable='Final Energy|Residential and Commercial').timeseries()\n",
+ "bld.index = bld.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bld_ele_vars = ['Final Energy|Residential and Commercial|Electricity']\n",
+ "add_stats_share(stats_c24, bld_ele_vars, 'electricity', bld, 'energy demand in buildings', [2050])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "trp = df.filter(variable='Final Energy|Transportation').timeseries()\n",
+ "trp.index = trp.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "var_trp_low = [\n",
+ " 'Final Energy|Transportation|Electricity',\n",
+ " 'Final Energy|Transportation|Hydrogen',\n",
+ " 'Final Energy|Transportation|Liquids|Biomass'\n",
+ "]\n",
+ "\n",
+ "add_stats_share(stats_c24, var_trp_low, 'low-emission energy', trp, 'energy demand in transport', [2050])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c24.summarize(center='median', interquartile=True, custom_format='{:.0f}')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statement C2.5: Transitions of land use\n",
+ "\n",
+ "Please refer to Figure 2.24 in Chapter 2 of the SR15 for details."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statement C2.6: Energy-related investment costs\n",
+ "\n",
+ "Please refer to Figure 2.27 in Chapter 2 of the SR15 for details."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statement C2.7: Marginal abatement costs\n",
+ "\n",
+ "Please refer to the notebook [sr15_2.5_carbon_price_analysis](sr15_2.5_carbon_price_analysis.ipynb) in this folder\n",
+ "for the detailed assessment."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statement C3: Cumulative carbon dioxide removal\n",
+ "\n",
+ "Please refer to the notebook [sr15_2.3.4_carbon_dioxide_removal](sr1p5_2.3.4_carbon_dioxide_removal.ipynb) in this folder\n",
+ "for the detailed assessment."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statement C3.2: Carbon capture and sequestration"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c32 = pyam.Statistics(df=df, filters=filters_15_no_lo, rows=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "beccs = (\n",
+ " df.filter(variable='Carbon Sequestration|CCS|Biomass', year=[2030, 2050, 2100])\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c32.add(beccs, header='Deployment of CDR', row='BECCS')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_c32.summarize(fullrange=True, custom_format='{:.0f}')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Please refer to the notebook [sr15_2.3.4_carbon_dioxide_removal](sr1p5_2.3.4_carbon_dioxide_removal.ipynb) in this folder for the additional assessment."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Statement D1.1: CO2 emissions reductions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_d11 = pyam.Statistics(df=df, filters=filters_15_no_lo)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ghg_ar4 = (\n",
+ " df.filter(variable='Emissions|Kyoto Gases (AR4-GWP100)')\n",
+ " .convert_unit({'Mt CO2-equiv/yr': ('Gt CO2-equiv/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_d11.add(ghg_ar4[[compare_year, 2030]], header='Kyoto GHG emissions (Gt CO2-eq/yr)')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_d11.add((ghg_ar4[2030] / ghg_ar4[compare_year] - 1) * 100,\n",
+ " header='Reduction of Kyoto GHG emissions',\n",
+ " subheader='2030 relative to {} (%)'.format(compare_year))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats_d11.summarize(fullrange=True, custom_format='{:.1f}')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Show pathways that limit warming to 1.5 with no or low overshoot that exceed the threshold of 35Gt CO2-eq/yr in 2030."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ghg_ar4_15 = pyam.filter_by_meta(ghg_ar4, df, category=cats_15_no_lo)\n",
+ "ghg_ar4_15[ghg_ar4_15[2030] > 35].dropna(axis=1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [default]",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.0_categories_indicators.ipynb b/assessment/sr15_2.0_categories_indicators.ipynb
new file mode 100644
index 0000000..4c39fc7
--- /dev/null
+++ b/assessment/sr15_2.0_categories_indicators.ipynb
@@ -0,0 +1,2172 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Scenario categorization and indicators\n",
+ "\n",
+ "This notebook assigns the categorization by warming outcome and computes a range of descriptive indicators\n",
+ "for the scenario assessment of the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "It generates a `sr15_metadata_indicators.xlsx` spreadsheet, which is used in other notebooks for this assessment\n",
+ "for categorization and extracting descriptive indicators.\n",
+ "\n",
+ "## Scenario ensemble data\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer).\n",
+ "\n",
+ "Bibliographic details of the scenario ensemble and all studies that contributed scenarios to the ensemble\n",
+ "are included in this repository\n",
+ "as [Endnote (enl)](../bibliography/iamc_1.5c_scenario_data.enl),\n",
+ "[Reference Manager (ris)](../bibliography/iamc_1.5c_scenario_data.ris),\n",
+ "and [BibTex (bib)](../bibliography/iamc_1.5c_scenario_data.bib) format.\n",
+ "\n",
+ "## License and recommended citation\n",
+ "\n",
+ "This notebook is licensed under the Apache License, Version 2.0.\n",
+ "\n",
+ "Please refer to the [README](../README.md) for the recommended citation of the scenario ensemble and the notebooks in this repository.\n",
+ "\n",
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import dependencies and define general notebook settings"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import math\n",
+ "import io\n",
+ "import yaml\n",
+ "import re\n",
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "from IPython.display import display"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Introduction and tutorial for the `pyam` package\n",
+ "\n",
+ "This notebook (and all other analysis notebooks in this repository) uses the `pyam` package,\n",
+ "an open-source Python package for IAM scenario analysis and visualization\n",
+ "([https://software.ene.iiasa.ac.at/pyam/](http://software.ene.iiasa.ac.at/pyam/)).\n",
+ "\n",
+ "For an introduction of the notation and features of the `pyam` package,\n",
+ "please refer to [github.com/IAMconsortium/pyam/tutorial/pyam_first_steps](https://github.com/IAMconsortium/pyam/blob/master/tutorial/pyam_first_steps.ipynb). \n",
+ "The tutorial will take you through the basic functions and options used here,\n",
+ "and provide further introduction and guidelines."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pyam\n",
+ "logger = pyam.logger()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Import Matplotlib and set figure layout defaults in line with SR1.5 guidelines"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario snapshot and define auxiliary dictionaries\n",
+ "\n",
+ "This notebook only assigns indicator based on global timeseries data.\n",
+ "\n",
+ "The dictionary `meta_tables` is used to collect definitions\n",
+ "of categories and secondary scenario classification throughout this script.\n",
+ "These definitions are exported to the metadata/categorization Excel workbook\n",
+ "at the end of the script for completeness.\n",
+ "The dictionary `meta_docs` collects definitions used for the documentation tags\n",
+ "in the online scenario explorer.\n",
+ "\n",
+ "The dictionary `specs` collects lists and the run control specifications to be exported to JSON\n",
+ "and used by other notebooks for the SR1.5 scenario analysis.\n",
+ "\n",
+ "The `plotting_args` dictionary assigns the default plotting arguemnts in this notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "meta_tables = {}\n",
+ "meta_docs = {}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "specs = {}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plotting_args = {'color': 'category', 'linewidth': 0.2}\n",
+ "specs['plotting_args'] = plotting_args"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Verify completeness of scenario submissions for key variables\n",
+ "\n",
+ "Verify that every scenario except for *Shell Sky* and the historical reference scenarios reports CO2 Emissions in 2030."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.require_variable(variable='Emissions|CO2', year=2030, exclude_on_fail=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Check MAGICC postprocessing prior to categorization\n",
+ "\n",
+ "Assign scenarios that could not be postprocessed by probabilistic MAGICC to respective categories: \n",
+ " - data not available for full century\n",
+ " - insufficient reporting of emission species\n",
+ " - reference scenario"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta(name='category', meta= 'uncategorized')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "reference = sr1p5.filter(model='Reference')\n",
+ "pd.DataFrame(index=reference.meta.index)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta(meta='reference', name='category', index=reference)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "no_climate_assessment = (\n",
+ " sr1p5.filter(category='uncategorized').meta.index\n",
+ " .difference(sr1p5.filter(year=2100, variable='Emissions|CO2').meta.index)\n",
+ ")\n",
+ "pd.DataFrame(index=no_climate_assessment)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta(meta='no-climate-assessment', name='category', index=no_climate_assessment)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Categorization of scenarios\n",
+ "\n",
+ "This section applies the categorization of scenario as defined in Chapter 2 of the Special Report\n",
+ "for unique assignment of scenarios.\n",
+ "\n",
+ "The category specification as agreed upon at LAM 3 in Malmö is repeated here for easier reference.\n",
+ "\n",
+ "The term $P_{x°C}$ refers to the probability of exceeding warming of $x°C$ throughout the century in at least one year\n",
+ "and $P_{x°C}(y)$ refers to the probability of exceedance in a specific year $y$.\n",
+ "\n",
+ "|**Categories** |**Subcategories**|**Probability to exceed warming threshold**|**Acronym** |**Color** |\n",
+ "|---------------|-----------------|-------------------------------------------|-----------------|----------------|\n",
+ "| Below 1.5°C | Below 1.5°C (I) | $P_{1.5°C} \\leq 0.34$ | Below 1.5C (I) | xkcd:baby blue |\n",
+ "| | Below 1.5°C (II)| $0.34 < P_{1.5°C} \\leq 0.50$ | Below 1.5C (II) | |\n",
+ "| 1.5°C return with low OS | Lower 1.5°C return with low OS | $0.50 < P_{1.5°C} \\leq 0.67$ and $P_{1.5°C}(2100) \\leq 0.34$ |(Lower) 1.5C low OS | xkcd:bluish |\n",
+ "| | Higher 1.5°C return with low OS | $0.50 < P_{1.5°C} \\leq 0.67$ and $0.34 < P_{1.5°C}(2100) \\leq 0.50$ |(Higher) 1.5C low OS | |\n",
+ "| 1.5°C return with high OS | Lower 1.5°C return with high OS | $0.67 < P_{1.5°C}$ and $P_{1.5°C}(2100) \\leq 0.34$ | (Lower) 1.5C high OS | xkcd:darkish blue |\n",
+ "| | Higher 1.5°C return with high OS | $0.67 < P_{1.5°C}$ and $0.34 < P_{1.5°C}(2100) \\leq 0.50$ | (Higher) 1.5C high OS | |\n",
+ "| Lower 2.0°C | | $P_{2.0°C} \\leq 0.34$ (excluding above) | Lower 2C | xkcd:orange |\n",
+ "| Higher 2.0°C | | $0.34 < P_{2.0°C} \\leq 0.50$ (excluding above) | Higher 2C | xkcd:red | \n",
+ "| Above 2.0°C | | $P_{2.0°C} > 0.50$ for at least 1 year | Above 2C | darkgrey | "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Category definitions to Excel\n",
+ "\n",
+ "The following dictionary repeats the category definitions from the table above\n",
+ "and saves them as a `pandas.DataFrame` to a dictionary `meta_tables`.\n",
+ "Throughout the notebook, this dictionary is used to collect definitions\n",
+ "of categories and secondary scenario classification.\n",
+ "These definitions are exported to the metadata/categorization Excel workbook\n",
+ "at the end of the script for easy reference."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "dct = {'Categories of scenarios': \n",
+ " ['Below 1.5°C', \n",
+ " '', \n",
+ " '1.5°C return with low overshoot',\n",
+ " '',\n",
+ " '1.5°C return with high overshoot',\n",
+ " '',\n",
+ " 'Lower 2.0°C',\n",
+ " 'Higher 2.0°C',\n",
+ " 'Above 2.0°C'],\n",
+ " 'Subcategories': \n",
+ " ['Below 1.5°C (I)', \n",
+ " 'Below 1.5°C (II)', \n",
+ " 'Lower 1.5°C return with low overshoot',\n",
+ " 'Higher 1.5°C return with low overshoot',\n",
+ " 'Lower 1.5°C return with high overshoot',\n",
+ " 'Higher 1.5°C return with high overshoot',\n",
+ " '',\n",
+ " '',\n",
+ " ''],\n",
+ " 'Criteria for assignment to category':\n",
+ " ['P1.5°C ≤ 0.34',\n",
+ " '0.34 < P1.5°C ≤ 0.50',\n",
+ " '0.50 < P1.5°C ≤ 0.67 and P1.5°C(2100) ≤ 0.34',\n",
+ " '0.50 < P1.5°C ≤ 0.67 and 0.34 < P1.5°C(2100) ≤ 0.50',\n",
+ " '0.67 < P1.5°C and P1.5°C(2100) ≤ 0.34',\n",
+ " '0.67 < P1.5°C and 0.34 < P1.5°C(2100) ≤ 0.50',\n",
+ " 'P2.0°C ≤ 0.34 (excluding above)',\n",
+ " '0.34 < P2.0°C ≤ 0.50 (excluding above)',\n",
+ " 'P2.0°C > 0.50 during at least 1 year'\n",
+ " ],\n",
+ " 'Acronym':\n",
+ " ['Below 1.5C (I)',\n",
+ " 'Below 1.5C (II)',\n",
+ " 'Lower 1.5C low overshoot',\n",
+ " 'Higher 1.5C low overshoot',\n",
+ " 'Lower 1.5C high overshoot',\n",
+ " 'Higher 1.5C high overshoot',\n",
+ " 'Lower 2C',\n",
+ " 'Higher 2C',\n",
+ " 'Above 2C'],\n",
+ " 'Color':\n",
+ " ['xkcd:baby blue',\n",
+ " '',\n",
+ " 'xkcd:bluish',\n",
+ " '',\n",
+ " 'xkcd:darkish blue',\n",
+ " '',\n",
+ " 'xkcd:orange',\n",
+ " 'xkcd:red',\n",
+ " 'darkgrey']\n",
+ " }\n",
+ "cols = ['Categories of scenarios', 'Subcategories', 'Criteria for assignment to category', 'Acronym', 'Color']\n",
+ "categories_doc = pd.DataFrame(dct)[cols]\n",
+ "meta_tables['categories'] = categories_doc\n",
+ "meta_docs['category'] = 'Categorization of scenarios by global warming impact'\n",
+ "meta_docs['subcategory'] = 'Sub-categorization of scenarios by global warming impact'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "other_cats = ['no-climate-assessment', 'reference']\n",
+ "\n",
+ "cats = ['Below 1.5C', '1.5C low overshoot', '1.5C high overshoot', 'Lower 2C', 'Higher 2C', 'Above 2C']\n",
+ "all_cats = cats + other_cats\n",
+ "\n",
+ "subcats = dct['Acronym']\n",
+ "all_subcats = subcats + other_cats"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "specs['cats'] = cats\n",
+ "specs['all_cats'] = all_cats\n",
+ "\n",
+ "specs['subcats'] = subcats\n",
+ "specs['all_subcats'] = all_subcats"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Subcategory assignment\n",
+ "\n",
+ "We first assign the subcategories, then aggregate those assignment to the main categories.\n",
+ "The categories assigned above to indicate reasons for non-processing by MAGICC are copied over to the subcategories.\n",
+ "\n",
+ "Keep in mind that setting a category will re-assign scenarios (in case they have already been assigned).\n",
+ "So in case of going back and forth in this notebook (i.e., not executing the cells in the correct order), \n",
+ "make sure to reset the categorization."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def warming_exccedance_prob(x):\n",
+ " return 'AR5 climate diagnostics|Temperature|Exceedance Probability|{} °C|MAGICC6'.format(x)\n",
+ "\n",
+ "expected_warming = 'AR5 climate diagnostics|Temperature|Global Mean|MAGICC6|Expected value'\n",
+ "median_warming = 'AR5 climate diagnostics|Temperature|Global Mean|MAGICC6|MED'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta(meta=sr1p5['category'], name='subcategory')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pyam.categorize(sr1p5, exclude=False, subcategory='uncategorized',\n",
+ " value='Below 1.5C (I)', name='subcategory',\n",
+ " criteria={warming_exccedance_prob(1.5): {'up': 0.34}},\n",
+ " color='xkcd:baby blue')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pyam.categorize(sr1p5, exclude=False, subcategory='uncategorized',\n",
+ " value='Below 1.5C (II)', name='subcategory',\n",
+ " criteria={warming_exccedance_prob(1.5): {'up': 0.50}},\n",
+ " color='xkcd:baby blue')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "To categorize by a variable using multiple filters (here: less than 66% probability of exceeding 1.5°C at any point during the century and less than 34% probability of exceeding that threshold in 2100) requires to perform the assignment in three steps - first, categorize to an intermediate `low OS` category and, in a second step, assign to the category in question. The third step resets all scenarios still categorized as intermediate after the second step back to `uncategorized`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pyam.categorize(sr1p5, exclude=False, subcategory='uncategorized',\n",
+ " value='low overshoot', name='subcategory',\n",
+ " criteria={warming_exccedance_prob(1.5): {'up': 0.67}})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pyam.categorize(sr1p5, exclude=False, subcategory='low overshoot',\n",
+ " value='Lower 1.5C low overshoot', name='subcategory',\n",
+ " criteria={warming_exccedance_prob(1.5): {'up': 0.34, 'year': 2100}},\n",
+ " color='xkcd:bluish')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pyam.categorize(sr1p5, exclude=False, subcategory='low overshoot',\n",
+ " value='Higher 1.5C low overshoot', name='subcategory',\n",
+ " criteria={warming_exccedance_prob(1.5): {'up': 0.50, 'year': 2100}},\n",
+ " color='xkcd:bluish')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Display scenarios that satisfy the `low overshoot` criterion\n",
+ "but are not assigned to `Lower 1.5C lower overshoot` or `Higher 1.5C lower overshoot`.\n",
+ "Then, reset them to uncategorized."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.filter(subcategory='low overshoot').meta"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta(meta='uncategorized', name='subcategory', index=sr1p5.filter(subcategory='low overshoot'))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Determine all scenarios with a probability to exceed 1.5°C greater than 66% in any year throughout the century.\n",
+ "The function `categorize()` cannot be used for this selection, because it would either check for the criteria being true for all years or for a particular year."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(exclude=False, subcategory='uncategorized', variable=warming_exccedance_prob(1.5)).timeseries()\n",
+ "sr1p5.set_meta(meta='high overshoot', name='subcategory', \n",
+ " index=df[df.apply(lambda x: max(x), axis=1) > 0.66].index)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pyam.categorize(sr1p5, exclude=False, subcategory='high overshoot',\n",
+ " value='Lower 1.5C high overshoot', name='subcategory',\n",
+ " criteria={warming_exccedance_prob(1.5): {'up': 0.34, 'year': 2100}},\n",
+ " color='xkcd:darkish blue')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pyam.categorize(sr1p5, exclude=False, subcategory='high overshoot',\n",
+ " value='Higher 1.5C high overshoot', name='subcategory',\n",
+ " criteria={warming_exccedance_prob(1.5): {'up': 0.50, 'year': 2100}},\n",
+ " color='xkcd:darkish blue')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Reset scenarios that satisfy the `high overshoot` criterion\n",
+ "but are not assigned to `Lower 1.5C high overshoot` or `Higher 1.5C high overshoot`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta(meta='uncategorized', name='subcategory', index=sr1p5.filter(subcategory='high overshoot'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pyam.categorize(sr1p5, exclude=False, subcategory='uncategorized',\n",
+ " value='Lower 2C', name='subcategory',\n",
+ " criteria={warming_exccedance_prob(2.0): {'up': 0.34}},\n",
+ " color='xkcd:orange')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pyam.categorize(sr1p5, exclude=False, subcategory='uncategorized',\n",
+ " value='Higher 2C', name='subcategory',\n",
+ " criteria={warming_exccedance_prob(2.0): {'up': 0.50}},\n",
+ " color='xkcd:red')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pyam.categorize(sr1p5, exclude=False, subcategory='uncategorized',\n",
+ " value='Above 2C', name='subcategory',\n",
+ " criteria={warming_exccedance_prob(2.0): {'up': 1.0}},\n",
+ " color='darkgrey')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Aggregation of subcategories to categories"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "rc = pyam.run_control()\n",
+ "def assign_rc_color_from_sub(cat, sub):\n",
+ " rc.update({'color': {'category': {cat: rc['color']['subcategory'][sub]}}})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta(meta='Below 1.5C', name='category',\n",
+ " index=sr1p5.filter(subcategory=['Below 1.5C (I)', 'Below 1.5C (II)']).meta.index)\n",
+ "assign_rc_color_from_sub('Below 1.5C', 'Below 1.5C (II)')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta(meta='1.5C low overshoot', name='category',\n",
+ " index=sr1p5.filter(subcategory=['Lower 1.5C low overshoot', 'Higher 1.5C low overshoot']))\n",
+ "assign_rc_color_from_sub('1.5C low overshoot', 'Lower 1.5C low overshoot')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta(meta='1.5C high overshoot', name='category',\n",
+ " index=sr1p5.filter(subcategory=['Lower 1.5C high overshoot', 'Higher 1.5C high overshoot']))\n",
+ "assign_rc_color_from_sub('1.5C high overshoot', 'Lower 1.5C high overshoot')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats_non15 = ['Lower 2C', 'Higher 2C', 'Above 2C']\n",
+ "df_2c = sr1p5.filter(subcategory=cats_non15)\n",
+ "sr1p5.set_meta(meta=df_2c['subcategory'], name='category')\n",
+ "\n",
+ "for c in cats_non15:\n",
+ " assign_rc_color_from_sub(c, c)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Additional assessment of categorization\n",
+ "\n",
+ "Check whether there are any scenarios that return to 1.5°C by the end of the century and exceed the 2°C threshold with a likelyhood higher than 34% or 50% (i.e., the `Lower 2C` or the `Higher 2C` categories respectively). Having scenario categorized as `1.5C` but with a higher-than-50% probability of exceeding 2°C at some point in the century may need to be considered separately in subsequent assessment."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats_15 = ['Below 1.5C', '1.5C low overshoot', '1.5C high overshoot']\n",
+ "specs['cats_15'] = cats_15"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats_15_no_lo = ['Below 1.5C', '1.5C low overshoot']\n",
+ "specs['cats_15_no_lo'] = cats_15_no_lo"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats_2 = ['Lower 2C', 'Higher 2C']\n",
+ "specs['cats_2'] = cats_2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(exclude=False, category=cats_15, variable=warming_exccedance_prob(2.0)).timeseries()\n",
+ "ex_prob_2 = df.apply(lambda x: max(x))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if max(ex_prob_2) > 0.34:\n",
+ " logger.warning('The following 1.5C-scenarios are not `Lower 2C` scenarios:')\n",
+ " display(df[df.apply(lambda x: max(x), axis=1) > 0.34])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if max(ex_prob_2) > 0.50:\n",
+ " logger.warning('The following 1.5C-scenarios are not `2C` scenarios:')\n",
+ " display(df[df.apply(lambda x: max(x), axis=1) > 0.50])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Counting and evaluation of scenario assignment categories\n",
+ "\n",
+ "Count the number of scenarios assigned to each category.\n",
+ "\n",
+ "This table is the basis for **Tables 2.1 and 2.A.11** in the SR1.5."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "lst = sr1p5.meta.groupby(['category', 'subcategory']).count()\n",
+ "(\n",
+ " lst\n",
+ " .reindex(all_cats, axis='index', level=0)\n",
+ " .reindex(all_subcats, axis='index', level=1)\n",
+ " .rename(columns={'exclude': 'count'})\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Check whether any scenarios are still marked as `uncategorized`. This may be due to missing MAGICC postprocessing."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if any(sr1p5['category'] == 'uncategorized'):\n",
+ " logger.warning('There are scenarios that are no yet categorized!')\n",
+ " display(sr1p5.filter(category='uncategorized').meta)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Validation of Kyoto GHG emissions range (SAR-GWP100)\n",
+ "\n",
+ "Validate all scenarios whther aggregate Kyoto gases are outside the range as assessed by the Second Assessment Report (SAR) using the Global Warming Potential over 100 years (GWP100). These scenarios are excluded from some figures and tables in the assessment."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "invalid_sar_gwp = sr1p5.validate(criteria={'Emissions|Kyoto Gases (SAR-GWP100)':\n",
+ " {'lo': 44500, 'up': 53500, 'year':2010}}, exclude_on_fail=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name='Kyoto-GHG|2010 (SAR)'\n",
+ "sr1p5.set_meta(meta='in range', name=name)\n",
+ "sr1p5.set_meta(meta='exclude', name=name, index=invalid_sar_gwp)\n",
+ "\n",
+ "meta_docs[name] = 'Indicator whether 2010 Kyoto-GHG reported by the scenario (as assessed by IPCC SAR) are in the valid range'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Assignment of baseline scenarios\n",
+ "\n",
+ "This section assigns a `baseline` reference for scenarios from selected model intercomparison projects and indivitual submissions."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def set_baseline_reference(x):\n",
+ " m, s = (x.name[0], x.name[1])\n",
+ " \n",
+ " b = None\n",
+ " if s.startswith('SSP') and not 'Baseline' in s:\n",
+ " b = '{}Baseline'.format(s[0:5])\n",
+ " if s.startswith('CD-LINKS') and not 'NoPolicy' in s:\n",
+ " b = '{}NoPolicy'.format(s[0:9])\n",
+ " if s.startswith('EMF33') and not 'Baseline' in s:\n",
+ " b = '{}Baseline'.format(s[0:6])\n",
+ " if s.startswith('ADVANCE') and not 'NoPolicy' in s:\n",
+ " b = '{}NoPolicy'.format(s[0:8])\n",
+ " if s.startswith('GEA') and not 'base' in s:\n",
+ " b = '{}base'.format(s[0:8])\n",
+ " if s.startswith('TERL') and not 'Baseline' in s:\n",
+ " b = s.replace('15D', 'Baseline').replace('2D', 'Baseline')\n",
+ " if s.startswith('SFCM') and not 'Baseline' in s:\n",
+ " b = s.replace('1p5Degree', 'Baseline').replace('2Degree', 'Baseline')\n",
+ " if s.startswith('CEMICS') and not s == 'CEMICS-Ref':\n",
+ " b = 'CEMICS-Ref'\n",
+ " if s.startswith('SMP') and not 'REF' in s:\n",
+ " if s.endswith('Def') or s.endswith('regul'):\n",
+ " b = 'SMP_REF_Def'\n",
+ " else:\n",
+ " b = 'SMP_REF_Sust'\n",
+ " if s.startswith('DAC'):\n",
+ " b = 'BAU'\n",
+ " \n",
+ " # check that baseline scenario exists for specific model `m`\n",
+ " if (m, b) in sr1p5.meta.index:\n",
+ " return b\n",
+ " # else (or if scenario name not in list above), return None\n",
+ " return None"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'baseline'\n",
+ "sr1p5.set_meta(sr1p5.meta.apply(set_baseline_reference, raw=True, axis=1), name)\n",
+ "meta_docs[name] = 'Name of the respective baseline (or reference/no-policy) scenario'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Assignent of marker scenarios\n",
+ "\n",
+ "The following scenarios are used as marker throughout the analysis and visualization, cf. Figure 2.7 (SOD):\n",
+ "\n",
+ "|**Marker** |**Model & scenario name** |**Reference** | **Symbol** |\n",
+ "|------------|--------------------------------|-------------------------------|-----------------|\n",
+ "| *S1* | AIM/CGE 2.0 / SSP1-19 | Fujimori et al., 2017 | `white square` |\n",
+ "| *S2* | MESSAGE-GLOBIOM 1.0 / SSP2-19 | Fricko et al., 2017 | `yellow square` |\n",
+ "| *S5* | REMIND-MAgPIE 1.5 / SSP5-19 | Kriegler et al., 2017 | `black square` |\n",
+ "| *LED* | MESSAGEix-GLOBIOM 1.0 / LowEnergyDemand | Grubler et al., 2018 | `white circle` |"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "dct = {'Marker': \n",
+ " ['S1', \n",
+ " 'S2', \n",
+ " 'S5',\n",
+ " 'LED'],\n",
+ " 'Model and scenario name': \n",
+ " ['AIM/CGE 2.0 / SSP1-19', \n",
+ " 'MESSAGE-GLOBIOM 1.0 / SSP2-19', \n",
+ " 'REMIND-MAgPIE 1.5 / SSP5-19',\n",
+ " 'MESSAGEix-GLOBIOM 1.0 / LowEnergyDemand'],\n",
+ " 'Reference':\n",
+ " ['Fujimori et al., 2017',\n",
+ " 'Fricko et al., 2017',\n",
+ " 'Kriegler et al., 2017',\n",
+ " 'Grubler et al., 2018'],\n",
+ " 'Symbol':\n",
+ " ['white square',\n",
+ " 'yellow square',\n",
+ " 'black square',\n",
+ " 'white circle']\n",
+ "}\n",
+ "cols = ['Marker', 'Model and scenario name', 'Reference', 'Symbol']\n",
+ "markers_doc = pd.DataFrame(dct)[cols]\n",
+ "meta_tables['marker scenarios'] = markers_doc\n",
+ "meta_docs['marker'] = 'Illustrative pathways (marker scenarios)'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "specs['marker'] = ['S1', 'S2', 'S5', 'LED']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta('', 'marker')\n",
+ "rc.update({'marker': {'marker': {'': None}}})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = 'S1'\n",
+ "sr1p5.set_meta(m, 'marker',\n",
+ " sr1p5.filter(model='AIM/CGE 2.0', scenario='SSP1-19'))\n",
+ "rc.update({'marker': {'marker': {m: 's'}},\n",
+ " 'c': {'marker': {m: 'white'}},\n",
+ " 'edgecolors': {'marker': {m: 'black'}}}\n",
+ " )"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = 'S2'\n",
+ "sr1p5.set_meta(m, 'marker',\n",
+ " sr1p5.filter(model='MESSAGE-GLOBIOM 1.0', scenario='SSP2-19'))\n",
+ "rc.update({'marker': {'marker': {m: 's'}},\n",
+ " 'c': {'marker': {m: 'yellow'}},\n",
+ " 'edgecolors': {'marker': {m: 'black'}}})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = 'S5'\n",
+ "sr1p5.set_meta(m, 'marker',\n",
+ " sr1p5.filter(model='REMIND-MAgPIE 1.5', scenario='SSP5-19'))\n",
+ "rc.update({'marker': {'marker': {m: 's'}},\n",
+ " 'c': {'marker': {m: 'black'}},\n",
+ " 'edgecolors': {'marker': {m: 'black'}}})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = 'LED'\n",
+ "sr1p5.set_meta(m, 'marker',\n",
+ " sr1p5.filter(model='MESSAGEix-GLOBIOM 1.0', scenario='LowEnergyDemand'))\n",
+ "rc.update({'marker': {'marker': {m: 'o'}},\n",
+ " 'c': {'marker': {m: 'white'}},\n",
+ " 'edgecolors': {'marker': {m: 'black'}}})"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Visual analysis of emission and temperature pathways by category\n",
+ "\n",
+ "First, we plot all carbon dioxide emissions trajectories colored by category and the CO2 emissions from the AFOLU sector. Then, show the warming trajectories by category."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "horizon = list(range(2000, 2020, 5)) + list(range(2020, 2101, 10))\n",
+ "df = sr1p5.filter(year=horizon)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.filter(exclude=False, variable='Emissions|CO2').line_plot(**plotting_args, marker='marker')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.filter(exclude=False, variable='Emissions|CO2|AFOLU').line_plot(**plotting_args, marker='marker')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.filter(exclude=False, variable=expected_warming).line_plot(**plotting_args, marker='marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scientific references and publication status\n",
+ "The following block reads in an Excel table with the details of the scientific references for each scenario.\n",
+ "\n",
+ "The main cell of this section loops over all entries in this Excel table, filters for the relevant scenarios,\n",
+ "and assigns a short reference and the publication status. If multiple references are relevant for a scenario, the references are compiled, and the 'highest' publication status is written to the metadata."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ref_cols = ['project', 'model', 'scenario', 'reference', 'doi', 'bibliography']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta('undefined', 'reference')\n",
+ "sr1p5.set_meta('unknown', 'project')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "refs = pd.read_csv('../bibliography/scenario_references.csv', encoding='iso-8859-1')\n",
+ "\n",
+ "_refs = {'index': []}\n",
+ "for i in ref_cols:\n",
+ " _refs.update({i.title(): []})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for cols in refs.iterrows():\n",
+ " c = cols[1]\n",
+ " filters = {}\n",
+ " \n",
+ " # check that filters are defined\n",
+ " if c.model is np.NaN and c.scenario is np.NaN:\n",
+ " logger.warn('project `{}` on line {} has no filters assigned'\n",
+ " .format(c.project, cols[0]))\n",
+ " continue\n",
+ "\n",
+ " # filter for scenarios to apply the project and publication tags\n",
+ " filters = {}\n",
+ " for i in ['model', 'scenario']:\n",
+ " if c[i] is not np.NaN:\n",
+ " if \";\" in c[i]:\n",
+ " filters.update({i: re.sub(\";\", \"\", c[i]).split()})\n",
+ " else:\n",
+ " filters.update({i: c[i]})\n",
+ " \n",
+ " df = sr1p5.filter(**filters)\n",
+ " if df.scenarios().empty:\n",
+ " logger.warn('no scenarios satisfy filters for project `{}` on line {} ({})'\n",
+ " .format(c.project, cols[0], filters))\n",
+ " continue\n",
+ "\n",
+ " # write to meta-tables dictionary\n",
+ " _refs['index'].append(cols[0])\n",
+ " for i in ref_cols:\n",
+ " _refs[i.title()].append(c[i])\n",
+ "\n",
+ " sr1p5.meta.loc[df.meta.index, 'project'] = c['project']\n",
+ "\n",
+ " for i in df.meta.index:\n",
+ " r = c['reference']\n",
+ " sr1p5.meta.loc[i, 'reference'] = r if sr1p5.meta.loc[i, 'reference'] == 'undefined' \\\n",
+ " else '{}; {}'.format(sr1p5.meta.loc[i, 'reference'], r)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cols = [i.title() for i in ref_cols]\n",
+ "meta_tables['references'] = pd.DataFrame(_refs)[cols]\n",
+ "meta_docs['reference'] = 'Scientific references'\n",
+ "meta_docs['project'] = 'Project identifier contributing the scenario'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# TODO make this nicer or remove\n",
+ "sr1p5.meta.groupby(['project', 'category']).count()['reference'].unstack().reindex(columns=all_cats)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Peak warming and indicator of median global warming peak-and-decline\n",
+ "\n",
+ "Determine peak warming (relative to pre-industrial temperature) and end-of century warming \n",
+ "and add this to the scenario metadata.\n",
+ "Then, compute the \"peak-and-decline\" indicator as the difference between peak warming and warming in 2100."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def peak_warming(x, return_year=False):\n",
+ " peak = x[x == x.max()]\n",
+ " if return_year:\n",
+ " return peak.index[0]\n",
+ " else:\n",
+ " return float(max(peak))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "median_temperature = sr1p5.filter(variable=median_warming).timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'median warming at peak (MAGICC6)'\n",
+ "sr1p5.set_meta(median_temperature.apply(peak_warming, raw=False, axis=1), name)\n",
+ "meta_docs[name] = 'median warming above pre-industrial temperature at peak (°C) as computed by MAGICC6'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'year of peak warming (MAGICC6)'\n",
+ "sr1p5.set_meta(median_temperature.apply(peak_warming, return_year=True, raw=False, axis=1), name)\n",
+ "meta_docs[name] = 'year of peak median warming as computed by MAGICC6'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'median warming in 2100 (MAGICC6)'\n",
+ "sr1p5.set_meta(median_temperature[2100], name)\n",
+ "meta_docs[name] = 'median warming above at peak above pre-industrial temperature as computed by MAGICC6'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'median warming peak-and-decline (MAGICC6)'\n",
+ "peak_decline = sr1p5['median warming at peak (MAGICC6)'] - sr1p5['median warming in 2100 (MAGICC6)']\n",
+ "sr1p5.set_meta(peak_decline, name)\n",
+ "meta_docs[name] = 'median warming peak-and-decline from peak to temperature in 2100 (°C) as computed by MAGICC6'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Add mean temperature at peak from 'FAIR' model diagnostics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "median_temperature_fair = sr1p5.filter(variable='AR5 climate diagnostics|Temperature|Global Mean|FAIR|MED')\\\n",
+ " .timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'median warming at peak (FAIR)'\n",
+ "sr1p5.set_meta(median_temperature_fair.apply(peak_warming, raw=False, axis=1), name)\n",
+ "meta_docs[name] = 'median warming above pre-industrial temperature at peak (°C) as computed by FAIR'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'year of peak warming (FAIR)'\n",
+ "sr1p5.set_meta(median_temperature_fair.apply(peak_warming, return_year=True, raw=False, axis=1), name)\n",
+ "meta_docs[name] = 'year of peak median warming as computed by FAIR'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "sr1p5.filter(category=cats).scatter(ax=ax,\n",
+ " x='median warming at peak (MAGICC6)',\n",
+ " y='median warming at peak (FAIR)', color='category')\n",
+ "ax.plot(ax.get_xlim(), ax.get_xlim())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "sr1p5.scatter(ax=ax, x='year of peak warming (MAGICC6)', y='year of peak warming (FAIR)', color='category')\n",
+ "ax.plot(ax.get_xlim(), ax.get_xlim())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Computation of threshold exceedance year and 'overshoot' year count\n",
+ "\n",
+ "Determine the year when a scenario exceeds a specific temperature threshold, \n",
+ "and for how many years the threshold is exceeded. \n",
+ "\n",
+ "This section uses the function ``exceedance()`` to determine the exceedance and return years.\n",
+ "The function ``overshoot_severity()`` computes the cumulative exceedance of the 1.5°C threshold\n",
+ "(i.e., the sum of temperature-years above the threshold)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def exceedance(temperature, years, threshold):\n",
+ " exceedance_yr = None\n",
+ " return_yr = None\n",
+ " overshoot_yr_count = None\n",
+ " prev_temp = 0\n",
+ " prev_yr = None\n",
+ "\n",
+ " for yr, curr_temp in zip(years, temperature):\n",
+ " if np.isnan(curr_temp):\n",
+ " continue\n",
+ " \n",
+ " if exceedance_yr is None and curr_temp > threshold:\n",
+ " x = (curr_temp - prev_temp) / (yr - prev_yr) # temperature change per year\n",
+ " exceedance_yr = prev_yr + int((threshold - prev_temp) / x) + 1 # add one because int() rounds down\n",
+ " if exceedance_yr is not None and return_yr is None and curr_temp < threshold:\n",
+ " x = (prev_temp - curr_temp) / (yr - prev_yr) # temperature change per year\n",
+ " return_yr = prev_yr + int((prev_temp - threshold) / x) + 1\n",
+ " prev_temp = curr_temp\n",
+ " prev_yr = yr\n",
+ "\n",
+ " if return_yr is not None and exceedance_yr is not None:\n",
+ " overshoot_yr_count = int(return_yr - exceedance_yr)\n",
+ " if exceedance_yr is not None:\n",
+ " exceedance_yr = int(exceedance_yr)\n",
+ " if return_yr is not None:\n",
+ " return_yr = int(return_yr)\n",
+ "\n",
+ " return [exceedance_yr, return_yr, overshoot_yr_count]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "exceedance_meta = median_temperature.apply(exceedance, axis=1, raw=True,\n",
+ " years=median_temperature.columns, threshold=1.5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'exceedance year|1.5°C'\n",
+ "sr1p5.set_meta(exceedance_meta.apply(lambda x: x[0]), name)\n",
+ "meta_docs[name] = 'year in which the 1.5°C median warming threshold is exceeded'\n",
+ "\n",
+ "name = 'return year|1.5°C'\n",
+ "sr1p5.set_meta(exceedance_meta.apply(lambda x: x[1]), name)\n",
+ "meta_docs[name] = 'year in which median warming returns below the 1.5°C threshold'\n",
+ "\n",
+ "name = 'overshoot years|1.5°C'\n",
+ "sr1p5.set_meta(exceedance_meta.apply(lambda x: x[2]), name)\n",
+ "meta_docs[name] = 'number of years where 1.5°C median warming threshold is exceeded'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def overshoot_severity(x, meta):\n",
+ " exceedance_yr = meta.loc[x.name[0:2]]['exceedance year|1.5°C']\n",
+ " return_yr = meta.loc[x.name[0:2]]['return year|1.5°C'] - 1 \n",
+ " # do not include year in which mean temperature returns to below 1.5\n",
+ " if exceedance_yr > 0 and return_yr > 0:\n",
+ " return pyam.cumulative(x, exceedance_yr, return_yr) - (return_yr - exceedance_yr + 1) * 1.5"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'exceedance severity|1.5°C'\n",
+ "sr1p5.set_meta(median_temperature.apply(overshoot_severity, axis=1, raw=False, meta=sr1p5.meta), name)\n",
+ "meta_docs[name] = 'sum of median temperature exceeding the 1.5°C threshold'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "exceedance_meta = median_temperature.apply(exceedance, axis=1, raw=True,\n",
+ " years=median_temperature.columns, threshold=2)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'exceedance year|2.0°C'\n",
+ "sr1p5.set_meta(exceedance_meta.apply(lambda x: x[0]), name)\n",
+ "meta_docs[name] = 'year in which the 2.0°C median warming threshold is exceeded'\n",
+ "\n",
+ "name = 'return year|2.0°C'\n",
+ "sr1p5.set_meta(exceedance_meta.apply(lambda x: x[1]), name)\n",
+ "meta_docs[name] = 'year in which median warming returns below the 2.0°C threshold'\n",
+ "\n",
+ "name = 'overshoot years|2.0°C'\n",
+ "sr1p5.set_meta(exceedance_meta.apply(lambda x: x[2]), name)\n",
+ "meta_docs[name] = 'number of years where 2.0°C median warming threshold is exceeded'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Secondary categorization and meta-data assignment according to CO2 emissions"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Defining the range for cumulative indicators and units\n",
+ "\n",
+ "All cumulative indicators are computed over the time horizon 2016-2100 (including the year 2100 in every summation)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "baseyear = 2016\n",
+ "lastyear = 2100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def filter_and_convert(variable):\n",
+ " return (sr1p5\n",
+ " .filter(variable=variable)\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ " )\n",
+ "\n",
+ "unit = 'Gt CO2/yr'\n",
+ "cumulative_unit = 'Gt CO2'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2 = filter_and_convert('Emissions|CO2')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'minimum net CO2 emissions ({})'.format(unit)\n",
+ "sr1p5.set_meta(co2.apply(np.nanmin, axis=1), name)\n",
+ "meta_docs[name] = 'Minimum of net CO2 emissions over the century ({})'.format(unit)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Indicators from cumulative CO2 emissions over the entire century (2016-2100)\n",
+ "\n",
+ "Compute the total cumulative CO2 emissions for secondary categorization of scenarios.\n",
+ "Cumulative CO2 emissions are a first-order proxy for global mean temperature change.\n",
+ "Emissions are interpolated linearly between years. The `last_year` value is included in the summation.\n",
+ "\n",
+ "The function `pyam.cumulative()` defined below aggregates timeseries values from `first_year` until `last_year`,\n",
+ "including both first and last year in the total. The function assumes linear interpolation for years where no values are provided."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'cumulative CO2 emissions ({}-{}, {})'.format(baseyear, lastyear, cumulative_unit)\n",
+ "sr1p5.set_meta(co2.apply(pyam.cumulative, raw=False, axis=1, first_year=baseyear, last_year=lastyear), name)\n",
+ "meta_docs[name] = 'Cumulative net CO2 emissions from {} until {} (including the last year, {})'.format(\n",
+ " baseyear, lastyear, cumulative_unit)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ccs = filter_and_convert('Carbon Sequestration|CCS')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'cumulative CCS ({}-{}, {})'.format(baseyear, lastyear, cumulative_unit)\n",
+ "sr1p5.set_meta(ccs.apply(pyam.cumulative, raw=False, axis=1, first_year=baseyear, last_year=lastyear), name)\n",
+ "meta_docs[name] = 'Cumulative carbon capture and sequestration from {} until {} (including the last year, {})'.format(\n",
+ " baseyear, lastyear, cumulative_unit)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "beccs = filter_and_convert('Carbon Sequestration|CCS|Biomass')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'cumulative BECCS ({}-{}, {})'.format(baseyear, lastyear, cumulative_unit)\n",
+ "sr1p5.set_meta(beccs.apply(pyam.cumulative, raw=False, axis=1, first_year=baseyear, last_year=lastyear), name)\n",
+ "meta_docs[name] = 'Cumulative carbon capture and sequestration from bioenergy from {} until {} (including the last year, {})'.format(\n",
+ " baseyear, lastyear, cumulative_unit)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "seq_lu = filter_and_convert('Carbon Sequestration|Land Use')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'cumulative sequestration land-use ({}-{}, {})'.format(baseyear, lastyear, cumulative_unit)\n",
+ "sr1p5.set_meta(seq_lu.apply(pyam.cumulative, raw=False, axis=1, first_year=baseyear, last_year=lastyear), name)\n",
+ "meta_docs[name] = 'Cumulative carbon sequestration from land use from {} until {} (including the last year, {})'.format(\n",
+ " baseyear, lastyear, cumulative_unit)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Cumulative CO2 emissions until peak warming"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_from_meta_column(df, x, col):\n",
+ " val = df.meta.loc[x.name[0:2], col]\n",
+ " return val if val < np.inf else max(x.index)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'cumulative CO2 emissions ({} to peak warming, {})'.format(baseyear, cumulative_unit)\n",
+ "sr1p5.set_meta(co2.apply(lambda x: pyam.cumulative(x, first_year=baseyear,\n",
+ " last_year=get_from_meta_column(sr1p5, x,\n",
+ " 'year of peak warming (MAGICC6)')),\n",
+ " raw=False, axis=1), name)\n",
+ "meta_docs[name] = 'cumulative net CO2 emissions from {} until the year of peak warming as computed by MAGICC6 (including the year of peak warming, {})'.format(\n",
+ " baseyear, cumulative_unit)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "(\n",
+ " sr1p5\n",
+ " .filter(category=cats)\n",
+ " .scatter(x='cumulative CO2 emissions (2016 to peak warming, {})'.format(cumulative_unit),\n",
+ " y='median warming at peak (MAGICC6)', color='category')\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Cumulative CO2 emissions until net-zero of total emissions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def year_of_net_zero(data, years, threshold):\n",
+ " prev_val = 0\n",
+ " prev_yr = np.nan\n",
+ "\n",
+ " for yr, val in zip(years, data):\n",
+ " if np.isnan(val):\n",
+ " continue\n",
+ " \n",
+ " if val < threshold:\n",
+ " x = (val - prev_val) / (yr - prev_yr) # absolute change per year\n",
+ " return prev_yr + int((threshold - prev_val) / x) + 1 # add one because int() rounds down\n",
+ " \n",
+ " prev_val = val\n",
+ " prev_yr = yr\n",
+ " return np.inf"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'year of netzero CO2 emissions'\n",
+ "sr1p5.set_meta(co2.apply(year_of_net_zero, years=co2.columns, threshold=0, axis=1), name)\n",
+ "meta_docs[name] = 'year in which net CO2 emissions reach zero'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'cumulative CO2 emissions ({} to netzero, {})'.format(baseyear, cumulative_unit)\n",
+ "sr1p5.set_meta(co2.apply(lambda x: pyam.cumulative(x, first_year=baseyear,\n",
+ " last_year=get_from_meta_column(sr1p5, x,\n",
+ " 'year of netzero CO2 emissions')),\n",
+ " raw=False, axis=1), name)\n",
+ "meta_docs[name] = 'net CO2 emissions from {} until the year of peak warming (including the last year, {})'.format(\n",
+ " baseyear, cumulative_unit)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'warming at netzero (MAGICC6)'\n",
+ "sr1p5.set_meta(median_temperature.apply(lambda x: x[get_from_meta_column(sr1p5, x,\n",
+ " 'year of netzero CO2 emissions')],\n",
+ " raw=False, axis=1), name)\n",
+ "meta_docs[name] = 'median warming above pre-industrial temperatures in the year of net-zero CO2 emission (MAGICC, °C)'.format(\n",
+ " baseyear, cumulative_unit)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "(\n",
+ " sr1p5\n",
+ " .scatter(x='cumulative CO2 emissions (2016 to netzero, {})'.format(cumulative_unit),\n",
+ " y='warming at netzero (MAGICC6)', color='category')\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "(\n",
+ " sr1p5\n",
+ " .scatter(ax=ax, x='cumulative CO2 emissions (2016 to peak warming, {})'.format(cumulative_unit),\n",
+ " y='cumulative CO2 emissions (2016 to netzero, {})'.format(cumulative_unit),\n",
+ " color='category')\n",
+ ")\n",
+ "ax.plot(ax.get_xlim(), ax.get_xlim())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "(\n",
+ " sr1p5\n",
+ " .scatter(ax=ax, x='median warming at peak (MAGICC6)',\n",
+ " y='warming at netzero (MAGICC6)', color='category')\n",
+ ")\n",
+ "x = np.linspace(*ax.get_xlim())\n",
+ "ax.plot(ax.get_xlim(), ax.get_xlim())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "(\n",
+ " sr1p5\n",
+ " .scatter(ax=ax, x='median warming in 2100 (MAGICC6)',\n",
+ " y='warming at netzero (MAGICC6)', color='category')\n",
+ ")\n",
+ "x = np.linspace(*ax.get_xlim())\n",
+ "ax.plot(ax.get_xlim(), ax.get_xlim())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Categorization and meta-data assignment according to final energy demand\n",
+ "\n",
+ "Add a categorization column to the metadata categorization based on final energy demand at the end of the century."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "horizon = list(range(2000, 2020, 5)) + list(range(2020, 2101, 10))\n",
+ "df = sr1p5.filter(year=horizon)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fe_df = df.filter(variable='Final Energy')\n",
+ "fe_df.line_plot(**plotting_args, marker='marker')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fe = fe_df.timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'final energy|2100'\n",
+ "sr1p5.set_meta(fe[2100], name)\n",
+ "meta_docs[name] = 'Final energy demand at the end of the century (EJ/yr)'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Indicators on carbon price development\n",
+ "\n",
+ "Retrieve the carbon price timeseries and derive the following indicators:\n",
+ " - carbon price in 2030, 2050, and 2100 given both in 2010$ as reported by models and as NPV\n",
+ " - simple average of NPV (2030-2100)\n",
+ " - annual compounded NPV (2030-2100)\n",
+ " - continuously compounded NPV (2030-2100)\n",
+ "\n",
+ "All net present values (NPV) are given relative to the year 2020.\n",
+ "They are calculated assuming a 5% discount rate."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "dct = {'Indicator type': \n",
+ " ['Price by year',\n",
+ " 'Price by year (as NPV)',\n",
+ " 'Average (Avg) NPV',\n",
+ " 'Annual compounded (AC) NPV)',\n",
+ " 'Continuously compounded (CC) NPV',\n",
+ " '', 'Note on NPV'\n",
+ " ],\n",
+ " 'Description':\n",
+ " ['Global carbon price as reported by each scenario',\n",
+ " 'Global carbon price as reported by each scenario discounted to 2020 NPV',\n",
+ " 'Cumulative NPV carbon price from 2030 until 2100 divided by number of years (71)',\n",
+ " 'Annual compounded NPV carbon price from 2030 until 2100 divided by number of years (71)',\n",
+ " 'Continuously compounded NPV carbon price from 2030 until 2100 divided by number of years (71)',\n",
+ " '', 'All NPV indicators are discounted to 2020 using a 5% discount rate'\n",
+ " ]\n",
+ " }\n",
+ "meta_tables['carbon_price'] = pd.DataFrame(dct)[['Indicator type', 'Description']]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbonprice_df = sr1p5.filter(variable='Price|Carbon', year=range(2020, 2101, 10))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Plot the carbon price trajectories by category\n",
+ "\n",
+ "There are some outlier scenarios with very high carbon prices, so the following cell manually sets the limits of the y-axis."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, ax = plt.subplots()\n",
+ "carbonprice_df.filter(year=range(2020, 2101, 10)).line_plot(ax=ax, **plotting_args)\n",
+ "plt.ylim(ymax=10000, ymin=0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Show outliers for verification and assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price = carbonprice_df.timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price[carbon_price.apply(lambda x: max([i for i in x if not np.isnan(i)]) > 10000, axis=1)]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Compute net-present values of the carbon price"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price_npv = carbon_price.copy()\n",
+ "\n",
+ "r = 0.05\n",
+ "discount_year = 2020\n",
+ "npv_first_year = 2030\n",
+ "npv_last_year = 2100\n",
+ "\n",
+ "for y in carbon_price_npv.columns: \n",
+ " carbon_price_npv[y] = carbon_price_npv[y] / math.pow(1 + r, y - discount_year)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "discount_docstring = ' from {} until {} including the last year, '.format(npv_first_year, npv_last_year) + \\\n",
+ " 'discounted to {} using a {}% discount rate'.format(discount_year, r)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for y in [2030, 2050, 2100]:\n",
+ " name = 'carbon price|{}'.format(y)\n",
+ " sr1p5.set_meta(carbon_price[y], 'carbon price|{}'.format(y))\n",
+ " meta_docs[name] = 'carbon price in {} (2010USD/tCO2)'.format(y)\n",
+ " \n",
+ " name = 'carbon price|{} (NPV)'.format(y)\n",
+ " sr1p5.set_meta(carbon_price_npv[y], name)\n",
+ " meta_docs[name] = 'net-present value of carbon price in {} (2010USD/tCO2), discounted to {}'.format(\n",
+ " y, discount_year)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'carbon price|Avg NPV (2030-2100)'\n",
+ "sr1p5.set_meta(carbon_price_npv.apply(pyam.cumulative, first_year=2030, last_year=2100,\n",
+ " raw=False, axis=1)/71, name)\n",
+ "meta_docs[name] = 'continuously compounded net-present value of carbon prices (2010USD/tCO2)' + discount_docstring"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def compute_w1_annual(r, dt):\n",
+ " value = 0\n",
+ " for i in range(1, dt): # range does not include the last element, but this is 0 in this formula\n",
+ " value += math.pow(1 / (1 + r), i) * (1 - i / dt)\n",
+ " return value\n",
+ "\n",
+ "def compute_w2_annual(r, dt):\n",
+ " value = 0\n",
+ " for i in range(1, dt + 1): # range does not include the last element\n",
+ " value += math.pow(1 / (1 + r), i - dt) * (i / dt)\n",
+ " return value\n",
+ "\n",
+ "w1_annual = {}\n",
+ "w2_annual = {}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def compute_w1_compounded(r, dt):\n",
+ " return 1 / r - (1 - math.exp(-r * dt)) / (r * r * dt)\n",
+ "\n",
+ "def compute_w2_compounded(r, dt):\n",
+ " return - 1 / r + (math.exp(r * dt) - 1) / (r * r * dt)\n",
+ "\n",
+ "w1_compounded = {}\n",
+ "w2_compounded = {}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# this function is an adaptation of 'pyam.timeseries:cumulative()'\n",
+ "\n",
+ "def npv_weighted(x, first_year, last_year, w1, w2, w1_function, w2_function, r): \n",
+ " if min(x.index) > first_year or max(x.index) < last_year:\n",
+ " return np.nan\n",
+ "\n",
+ " x[first_year] = pyam.fill_series(x, first_year)\n",
+ " x[last_year] = pyam.fill_series(x, last_year)\n",
+ "\n",
+ " years = [i for i in x.index if i >= first_year and i <= last_year\n",
+ " and ~np.isnan(x[i])]\n",
+ " years.sort()\n",
+ "\n",
+ " # loop over years\n",
+ " if not np.isnan(x[first_year]) and not np.isnan(x[last_year]):\n",
+ " value = 0\n",
+ " for (i, yr) in enumerate(years[:-1]):\n",
+ " next_yr = years[i+1]\n",
+ " dt = next_yr - yr\n",
+ " if dt not in w1.keys():\n",
+ " w1[dt] = w1_function(r, dt)\n",
+ " if dt not in w2.keys():\n",
+ " w2[dt] = w2_function(r, dt) \n",
+ " # the summation is shifted to include the first year fully in sum,\n",
+ " # otherwise, would return a weighted average of `yr` and `next_yr`\n",
+ " value += w1[dt] * x[yr] + w2[dt] * x[next_yr]\n",
+ "\n",
+ " # the loop above does not include the last element in range `last_year`,\n",
+ " # therefore added explicitly\n",
+ " value += x[last_year]\n",
+ "\n",
+ " return value / (last_year - first_year + 1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'carbon price|AC NPV (2030-2100)'\n",
+ "sr1p5.set_meta(carbon_price_npv.apply(npv_weighted, first_year=npv_first_year, last_year=npv_last_year,\n",
+ " w1=w1_annual, w2=w2_annual, \n",
+ " w1_function=compute_w1_annual, w2_function=compute_w2_annual, r=r,\n",
+ " raw=False, axis=1), name)\n",
+ "meta_docs[name] = 'anually compounded net-present value of carbon prices (2010USD/tCO2)' + discount_docstring"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'carbon price|CC NPV (2030-2100)'\n",
+ "sr1p5.set_meta(carbon_price_npv.apply(npv_weighted, first_year=npv_first_year, last_year=npv_last_year, \n",
+ " w1=w1_compounded, w2=w2_compounded, \n",
+ " w1_function=compute_w1_compounded, w2_function=compute_w2_compounded, r=r,\n",
+ " raw=False, axis=1), name)\n",
+ "meta_docs[name] = 'continuously compounded net-present value of carbon prices (2010USD/tCO2)' + discount_docstring"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## View categorization and indicators, export metadata and grouping specifications\n",
+ "\n",
+ "The metadata (categorization and diagnostic indicators) is exported as an `xlsx` spreadsheet to be used by other scripts for subsequent analysis and visualization. The specifications of groupings and markers are exported as a `yaml` file to be imported by other notebooks."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "[i for i in sr1p5.meta.columns if i not in meta_docs.keys()]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.meta.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "_meta_docs = pd.DataFrame(meta_docs, index=[0]).T.reset_index()\n",
+ "_meta_docs.rename(columns={'index': 'Category or indicator', 0: 'Description'}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "writer = pd.ExcelWriter('sr15_metadata_indicators.xlsx')\n",
+ "pyam.utils.write_sheet(writer, 'meta', sr1p5.meta, index=True)\n",
+ "pyam.utils.write_sheet(writer, 'categories_indicators_doc', _meta_docs, index=False)\n",
+ "for name, df in meta_tables.items():\n",
+ " pyam.utils.write_sheet(writer, 'def_{}'.format(name), df)\n",
+ "writer.save()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "specs['run_control'] = rc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with io.open('sr15_specs.yaml', 'w', encoding='utf8') as outfile:\n",
+ " yaml.dump(specs, outfile, default_flow_style=False, allow_unicode=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [default]",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.3.1_range_of_assumptions.ipynb b/assessment/sr15_2.3.1_range_of_assumptions.ipynb
new file mode 100644
index 0000000..5fd25ba
--- /dev/null
+++ b/assessment/sr15_2.3.1_range_of_assumptions.ipynb
@@ -0,0 +1,274 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Assessment of underlying drivers and assumptions\n",
+ "\n",
+ "This notebook contains the assessment of underlying drivers and assumptions of the scenario ensemble \n",
+ "in **Section 2.3.1** and **Figure 2.4** for the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import io\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam\n",
+ "\n",
+ "from utils import boxplot_by_cat"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must have been generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "cats_15 = specs.pop('cats_15')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for figures and statistics\n",
+ "\n",
+ "First, set the list of years included in the plots. Then, define an auxiliary dictionary and function for easier display."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=sr1p5, category=cats, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to years interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "full_horizon = range(2010, 2101, 10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats, year=full_horizon)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set plotting settings for illustrative pathways"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "_rc = {\n",
+ " 'S1': dict(linewidth=3, linestyle='--'),\n",
+ " 'S2': dict(linewidth=4, linestyle=':'),\n",
+ " 'S5': dict(linewidth=3, linestyle='-.'),\n",
+ " 'LED': dict(linewidth=3, linestyle='-'),\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def line_plot_with_markers(ax, _df, name, panel):\n",
+ " _data = _df.filter(category=cats_15, keep=False).data\n",
+ " ax.plot(pyam.plotting.reshape_line_plot(_data, 'year', 'value'),\n",
+ " color='lightgrey')\n",
+ " ax.scatter(x=[], y=[], c='lightgrey', label='all scenarios')\n",
+ " y_pos = max(_data.value) - 0.05 * (max(_data.value) - min(_data.value))\n",
+ "\n",
+ " _data = _df.filter(category=cats_15).data\n",
+ " ax.plot(pyam.plotting.reshape_line_plot(_data, 'year', 'value'),\n",
+ " color='xkcd:baby blue')\n",
+ " ax.scatter(x=[], y=[], c='xkcd:baby blue', label='1.5°C pathways')\n",
+ "\n",
+ " for m in marker:\n",
+ " _data = _df.filter(marker=m).data\n",
+ " if not _data.empty:\n",
+ " ax.plot(pyam.plotting.reshape_line_plot(_data, 'year', 'value'),\n",
+ " color='xkcd:darkish blue', **_rc[m], label=m)\n",
+ " \n",
+ " ax.set_ylabel('{} ({})'.format(name, _data.unit.unique()[0]))\n",
+ " pyam.plotting.set_panel_label('({})'.format(panel), ax=ax)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, ax = plt.subplots(2, 2, figsize=(8, 6))\n",
+ "\n",
+ "pop = df.filter(variable='Population')\n",
+ "pop.convert_unit({'million': ['billion', 1/1000]}, inplace=True)\n",
+ "line_plot_with_markers(ax[0][0], pop, 'Population', 'a')\n",
+ "\n",
+ "gdp = df.filter(variable='GDP|PPP')\n",
+ "gdp.convert_unit({'billion US$2010/yr': ['trillion US$2010/yr', 1/1000]}, inplace=True)\n",
+ "line_plot_with_markers(ax[0][1], gdp, 'Gross World Product', 'b')\n",
+ "\n",
+ "final = df.filter(variable='Final Energy')\n",
+ "line_plot_with_markers(ax[1][0], final, 'Final Energy Demand', 'c')\n",
+ "\n",
+ "food = df.filter(variable='Food Demand')\n",
+ "line_plot_with_markers(ax[1][1], food, 'Food Demand', 'd')\n",
+ "\n",
+ "ax[0][0].legend(loc=1)\n",
+ "fig.tight_layout()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig.savefig('output/fig2.4_drivers_assumptions.png')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Export timeseries data to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "writer = pd.ExcelWriter('output/fig2.4_data_table.xlsx')\n",
+ "pyam.utils.write_sheet(writer, 'population', pyam.filter_by_meta(pop.timeseries(), **filter_args),\n",
+ " index=True)\n",
+ "pyam.utils.write_sheet(writer, 'gdp', pyam.filter_by_meta(gdp.timeseries(), **filter_args),\n",
+ " index=True)\n",
+ "pyam.utils.write_sheet(writer, 'final energy', pyam.filter_by_meta(final.timeseries(), **filter_args),\n",
+ " index=True)\n",
+ "pyam.utils.write_sheet(writer, 'food demand', pyam.filter_by_meta(food.timeseries(), **filter_args),\n",
+ " index=True)\n",
+ "writer.save()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [default]",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.3.3_global_emissions_characteristics.ipynb b/assessment/sr15_2.3.3_global_emissions_characteristics.ipynb
new file mode 100644
index 0000000..ffe338a
--- /dev/null
+++ b/assessment/sr15_2.3.3_global_emissions_characteristics.ipynb
@@ -0,0 +1,471 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Annual global emissions characteristics
of long-lived climate forcers\n",
+ "\n",
+ "This notebook plots the development of carbon dioxide emissions by different subsectors\n",
+ "for **Figure 2.6** in the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam\n",
+ "\n",
+ "from utils import boxplot_by_cat"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "all_cats = specs.pop('all_cats')\n",
+ "subcats = specs.pop('subcats')\n",
+ "all_subcats = specs.pop('all_subcats')\n",
+ "plotting_args = specs.pop('plotting_args')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2020, 2030, 2050, 2100]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.meta.rename(columns={'Kyoto-GHG|2010 (SAR)': 'kyoto_ghg_2010'}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(kyoto_ghg_2010='in range', category=cats, year=years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for filter and plotting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "save_name = 'output/fig2.6{}.{}'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=sr1p5, category=cats, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotting_args(name, filetype='png', hlines=[0]):\n",
+ " return {'categories': cats, 'column': 'category', 'years': years, 'add_marker': marker,\n",
+ " 'hlines': hlines, 'save': save_name.format(name, filetype)}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = []"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plot different emissions pathways by category"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ghg = (\n",
+ " df.filter(variable='Emissions|Kyoto Gases (AR4-GWP100)')\n",
+ " .convert_unit({'Mt CO2-equiv/yr': ('Gt CO2-equiv/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'kyoto'\n",
+ "_data = pyam.filter_by_meta(ghg, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, ylabel='Global Kyoto-GHG emissions (GtCO2e AR4GWP)',\n",
+ " **plotting_args('a_{}'.format(name)))\n",
+ "_data['species'] = name\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2 = (\n",
+ " df.filter(variable='Emissions|CO2')\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'co2_net_total'\n",
+ "_data = pyam.filter_by_meta(co2, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, ylabel='Global CO2 emissions (GtCO2)',\n",
+ " **plotting_args('b_{}'.format(name)), legend=False)\n",
+ "_data['species'] = name\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_afolu = (\n",
+ " df.filter(variable='Emissions|CO2|AFOLU')\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'co2_afolu'\n",
+ "_data = pyam.filter_by_meta(co2_afolu, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, ylabel='Global CO2 emissions from AFOLU (GtCO2)',\n",
+ " **plotting_args('c_{}'.format(name)), legend=False)\n",
+ "_data['species'] = name\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "n2o = (\n",
+ " df.filter(variable='Emissions|N2O')\n",
+ " .convert_unit({'kt N2O/yr': ('Mt N2O/yr', 0.001)}) \n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'n2o'\n",
+ "_data = pyam.filter_by_meta(n2o, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, ylabel='Global N2O emissions (MtN2O)',\n",
+ " **plotting_args('d_{}'.format(name), hlines=None),\n",
+ " legend=False)\n",
+ "_data['species'] = name\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_ene = (\n",
+ " df.filter(variable='Emissions|CO2|Energy and Industrial Processes')\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'co2_ffi'\n",
+ "_data = pyam.filter_by_meta(co2_ene, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, ylabel='Global CO2 emissions from fossil fuels and industry (GtCO2)',\n",
+ " **plotting_args('e_{}'.format(name)), legend=False)\n",
+ "_data['species'] = name\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_supply = (\n",
+ " df.filter(variable='Emissions|CO2|Energy|Supply')\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'co2_supply'\n",
+ "_data = pyam.filter_by_meta(co2_supply, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, ylabel='Global CO2 emissions from energy supply (GtCO2)',\n",
+ " **plotting_args('f_{}'.format(name)), legend=False)\n",
+ "_data['species'] = name\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_demand = (\n",
+ " df.filter(variable='Emissions|CO2|Energy|Demand')\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Exclude scenarios that report the CO2 emissions from energy demand as zero from this plot."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_demand[co2_demand.apply(lambda x: max(x), axis=1) < 0.1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_demand = co2_demand[co2_demand.apply(lambda x: max(x), axis=1) > 0.1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'co2_demand'\n",
+ "_data = pyam.filter_by_meta(co2_demand, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, ylabel='Global CO2 emissions from energy demand (GtCO2)',\n",
+ " **plotting_args('g_{}'.format(name)), legend=False)\n",
+ "_data['species'] = name\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Export timeseries data to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = pd.concat(data).set_index(['species', 'category', 'marker'], append=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data.reset_index().to_excel('output/fig2.6_data_table.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:anaconda]",
+ "language": "python",
+ "name": "conda-env-anaconda-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.3.3_global_emissions_statistics.ipynb b/assessment/sr15_2.3.3_global_emissions_statistics.ipynb
new file mode 100644
index 0000000..8dbdd03
--- /dev/null
+++ b/assessment/sr15_2.3.3_global_emissions_statistics.ipynb
@@ -0,0 +1,446 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Analysis of global CO2 and Kyoto emissions, (BE)CCS
and year of net-zero\n",
+ "\n",
+ "This notebook computes indicators and diagnostics of emissions pathways, the use of carbon capture and sequestration, and the timing of net-zero of different emissions categories \n",
+ "in the IPCC's _\"Special Report on Global Warming of 1.5°C\"_. The notebook generates the data for **Table 2.4** in the Special Report.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import pyam"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment\n",
+ "\n",
+ "Apply the filter by relevant years *after computing the year of netzero*."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.meta.rename(columns={'Kyoto-GHG|2010 (SAR)': 'kyoto_ghg_2010'}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(kyoto_ghg_2010='in range', category=cats)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Initialize a `pyam.Statistics` instance"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats = pyam.Statistics(df=df, groupby={'category': cats}, rows=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2030, 2050, 2100]\n",
+ "compare_years = [(2010, 2030), (2020, 2030), (2030, 2050)]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Function to compute the year of netzero and add growth statistics to the summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def year_of_net_zero(data, years, threshold):\n",
+ " prev_val = 0\n",
+ " prev_yr = np.nan\n",
+ "\n",
+ " for yr, val in zip(years, data):\n",
+ " if np.isnan(val):\n",
+ " continue\n",
+ " \n",
+ " if val < threshold:\n",
+ " x = (val - prev_val) / (yr - prev_yr) # absolute change per year\n",
+ " return prev_yr + int((threshold - prev_val) / x) + 1 # add one because int() rounds down\n",
+ " \n",
+ " prev_val = val\n",
+ " prev_yr = yr\n",
+ " return np.inf"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "header='Annual emissions/sequestration (GtCO2)'\n",
+ "header_change='Absolute annual change (GtCO2)'\n",
+ "header_zero='Timing of global zero'\n",
+ "\n",
+ "statistics_settings = dict(\n",
+ " header=header,\n",
+ " header_change=header_change,\n",
+ " header_zero= header_zero,\n",
+ " years=years,\n",
+ " compare_years=[(2010, 2030), (2020, 2030), (2030, 2050)],\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def add_statistics(data, row, years, compare_years,\n",
+ " header, header_change, header_zero, add_netzero=False):\n",
+ " stats.add(data[years], header=header, row=row)\n",
+ " for i, j in compare_years:\n",
+ " abs_ann_change = (data[j] - data[i]) / (j - i)\n",
+ " stats.add(abs_ann_change, header=header_change, row=row,\n",
+ " subheader='{}-{}'.format(i,j))\n",
+ " if add_netzero:\n",
+ " netzero = data.apply(year_of_net_zero, years=data.columns, threshold=0, axis=1)\n",
+ " stats.add(netzero, header=header_zero, row=row, subheader='year')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Get timeseries of total CO2 emissions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2 = (\n",
+ " df.filter(variable='Emissions|CO2')\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(co2, 'Total CO2 (net)', **statistics_settings, add_netzero=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_gross_seq_variables = [\n",
+ " 'Carbon Sequestration|CCS|Biomass',\n",
+ " 'Carbon Sequestration|Land Use',\n",
+ " 'Carbon Sequestration|Direct Air Capture',\n",
+ " 'Carbon Sequestration|Enhanced Weathering'\n",
+ "]\n",
+ "agg_sequestration = (\n",
+ " df.filter(variable=co2_gross_seq_variables)\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")\n",
+ "agg_sequestration = agg_sequestration.groupby(pyam.META_IDX).sum()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_ene_ind = (\n",
+ " df.filter(variable='Emissions|CO2|Energy and Industrial Processes')\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")\n",
+ "co2_ene_ind.index = co2_ene_ind.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_ene_ind_gross = (co2_ene_ind + agg_sequestration).combine_first(co2_ene_ind)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(co2_ene_ind_gross, 'CO2 from fossil fuels and industry (gross)', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(co2_ene_ind, 'CO2 from fossil fuels and industry (net)', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_afolu = (\n",
+ " df.filter(variable='Emissions|CO2|AFOLU')\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(co2_afolu, 'CO2 from AFOLU', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## CCS from bioenergy"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ccs_bio = (\n",
+ " df.filter(variable='Carbon Sequestration|CCS|Biomass')\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(ccs_bio, 'Bioenergy combined with carbon capture and storage (BECCS)',**statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Total greenhouse gases according to the Kyoto protocol"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ghg = (\n",
+ " df.filter(variable='Emissions|Kyoto Gases (AR4-GWP100)')\n",
+ " .convert_unit({'Mt CO2-equiv/yr': ('Gt CO2-equiv/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(ghg, 'Kyoto GHG (AR4, GtCO2e)', **statistics_settings, add_netzero=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Display and export summary statistics to `xlsx`\n",
+ "\n",
+ "Note that in Table 2.4 as printed in the pre-release of the Special Report following the approval plenary, the full range if shown for any cells with less than 7 scenarios, and interquartile ranges are shown otherwise.\n",
+ "This formatting was implemented manually ex-post, as it is currently not supported by the `pyam.Statistics` module."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "summary = stats.summarize(center='median', interquartile=True)\n",
+ "summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "summary.to_excel('output/table_2.4_emission_statistics.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [default]",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.3.3_short-lived_climate_forcers.ipynb b/assessment/sr15_2.3.3_short-lived_climate_forcers.ipynb
new file mode 100644
index 0000000..1774367
--- /dev/null
+++ b/assessment/sr15_2.3.3_short-lived_climate_forcers.ipynb
@@ -0,0 +1,371 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Analysis of short-lived non-CO2 emissions\n",
+ "\n",
+ "This notebook plots emissions of CH4, F-gases, BC and SO2 as shown in **Figure 2.7**\n",
+ "of the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam\n",
+ "\n",
+ "from utils import boxplot_by_cat"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "all_cats = specs.pop('all_cats')\n",
+ "subcats = specs.pop('subcats')\n",
+ "all_subcats = specs.pop('all_subcats')\n",
+ "plotting_args = specs.pop('plotting_args')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2010, 2030, 2050]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.meta.rename(columns={'Kyoto-GHG|2010 (SAR)': 'kyoto_ghg_2010'}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(kyoto_ghg_2010='in range', category=cats, year=years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for filter and plotting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "save_name = 'output/fig2.7{}.{}'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=sr1p5, category=cats, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "compare_years = [2030, 2050]\n",
+ "base_year = 2010"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotting_args(name, filetype='png'):\n",
+ " return {'categories': cats, 'column': 'category', 'years': years,\n",
+ " 'add_marker': marker,\n",
+ " 'save': save_name.format(name, filetype)}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = []"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plot different emissions pathways by category"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ch4 = df.filter(variable='Emissions|CH4').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "name = 'ch4'\n",
+ "label = 'Global CH4 emissions'\n",
+ "unit = 'MtCH4/yr'\n",
+ "_data = pyam.filter_by_meta(ch4, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, ylabel='{} ({})'.format(label, unit),\n",
+ " **plotting_args('a_{}'.format(name)))\n",
+ "_data['species'] = name\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fgases = df.filter(variable='Emissions|F-Gases').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'f-gases'\n",
+ "label = 'Global F-gas emissions'\n",
+ "unit = 'GtCO2e/yr'\n",
+ "\n",
+ "_data = pyam.filter_by_meta(fgases, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, ylabel='{} ({})'.format(label, unit),\n",
+ " **plotting_args('b_{}'.format(name)), legend=False)\n",
+ "_data['species'] = name\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bc = df.filter(variable='Emissions|BC').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'bc'\n",
+ "label = 'Global BC emissions'\n",
+ "unit = 'MtBC'\n",
+ "\n",
+ "_data = pyam.filter_by_meta(bc, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, ylabel='{} ({})'.format(label, unit),\n",
+ " **plotting_args('c_{}'.format(name)), legend=False)\n",
+ "_data['species'] = name\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "so2 = df.filter(variable='Emissions|Sulfur').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'so2'\n",
+ "label = 'Global SO2 emissions'\n",
+ "unit = 'MtSO2'\n",
+ "_data = pyam.filter_by_meta(so2, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, ylabel='{} ({})'.format(label, unit),\n",
+ " **plotting_args('d_{}'.format(name)), legend=False)\n",
+ "_data['species'] = name\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Export timeseries data to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = pd.concat(data).set_index(['species', 'category', 'marker'], append=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data.reset_index().to_excel('output/fig2.7_data_table.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:anaconda]",
+ "language": "python",
+ "name": "conda-env-anaconda-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.3.3_short-lived_climate_forcers_radiative_forcing.ipynb b/assessment/sr15_2.3.3_short-lived_climate_forcers_radiative_forcing.ipynb
new file mode 100644
index 0000000..da17808
--- /dev/null
+++ b/assessment/sr15_2.3.3_short-lived_climate_forcers_radiative_forcing.ipynb
@@ -0,0 +1,303 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Analysis of radiative forcing from short-lived climate-forcers\n",
+ "\n",
+ "This notebook plots the radiative forcing from short-lived climate forcers (SLCF)\n",
+ "shown in **Figure 2.8** of the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam\n",
+ "\n",
+ "from utils import boxplot_by_cat"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "all_cats = specs.pop('all_cats')\n",
+ "subcats = specs.pop('subcats')\n",
+ "all_subcats = specs.pop('all_subcats')\n",
+ "plotting_args = specs.pop('plotting_args')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2010, 2020, 2030, 2050, 2100]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.meta.rename(columns={'Kyoto-GHG|2010 (SAR)': 'kyoto_ghg_2010'}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(kyoto_ghg_2010='in range', category=cats, year=years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for filter and plotting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "save_name = 'output/fig2.8_effective_radiative_forcing.{}'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=sr1p5, category=cats, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotting_args(filetype='png'):\n",
+ " return {'categories': cats, 'column': 'category',\n",
+ " 'years': years, 'add_marker': marker,\n",
+ " 'save': save_name.format(filetype)}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Compute radiative forcing from short-lived climate forcers"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.filter(variable='AR5 climate diagnostics|Forcing|CO2|*').variables()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "rf_llcf_vars = [\n",
+ " 'AR5 climate diagnostics|Forcing|CO2|FAIR|MED',\n",
+ " 'AR5 climate diagnostics|Forcing|N2O|FAIR|MED'\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for v in ['AR5 climate diagnostics|Forcing|FAIR|MED'] + rf_llcf_vars:\n",
+ " df.require_variable(v, exclude_on_fail=True)\n",
+ "\n",
+ "df.filter(exclude=False, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "rf_all = df.filter(variable='AR5 climate diagnostics|Forcing|FAIR|MED').timeseries()\n",
+ "rf_all.index = rf_all.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "rf_llcf = df.filter(variable=rf_llcf_vars).timeseries()\n",
+ "rf_llcf = rf_llcf.groupby(pyam.META_IDX).sum()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "rf_slcf = rf_all - rf_llcf"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = pyam.filter_by_meta(rf_slcf, **filter_args)\n",
+ "boxplot_by_cat(data, **plotting_args(),\n",
+ " ylabel='Effective radiative forcing (W/m2)', )"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Export timeseries data to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data.reset_index().to_excel('output/fig2.8_data_table.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:anaconda]",
+ "language": "python",
+ "name": "conda-env-anaconda-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.3.4_carbon_dioxide_removal.ipynb b/assessment/sr15_2.3.4_carbon_dioxide_removal.ipynb
new file mode 100644
index 0000000..a96725a
--- /dev/null
+++ b/assessment/sr15_2.3.4_carbon_dioxide_removal.ipynb
@@ -0,0 +1,636 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Analysis of carbon dioxide removal (CDR)\n",
+ "\n",
+ "This notebook generates the assessment of carbon dioxide removal for **Figure 2.9** in the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "all_cats = specs.pop('all_cats')\n",
+ "subcats = specs.pop('subcats')\n",
+ "all_subcats = specs.pop('all_subcats')\n",
+ "plotting_args = specs.pop('plotting_args')\n",
+ "marker = specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for filter and plotting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=sr1p5, category=cats, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Retrieve carbon dioxide emissions and generate two auxiliary variables with net-negative CO2 emissions \n",
+ "\n",
+ "For easier aggregation of the timeseries later on towards different metrics of carbon dioxide removal, we introduce both a positive net-negative timeseries (A, where the removal of 1Gt CO2 is counted as a positive value) and a timeseries where the sequestered amount is defined as a negative value (B)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2 = df.filter(variable='Emissions|CO2').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### A) Net-negative CO2 emissions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_nn = co2.applymap(lambda x: - min(x, 0)).reset_index()\n",
+ "co2_nn.variable = 'Emissions|CO2|Net-negative'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_nn_df = pyam.IamDataFrame(co2_nn)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.data = df.data.append(co2_nn_df.data, ignore_index=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### B) Net-negative-negative CO2 emissions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_nn_neg = co2.applymap(lambda x: min(x, 0)).reset_index()\n",
+ "co2_nn_neg.variable = 'Emissions|CO2|Net-negative-negative'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_nn_neg_df = pyam.IamDataFrame(co2_nn_neg)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.data = df.data.append(co2_nn_neg_df.data, ignore_index=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Retrieve carbon dioxide emissions from agriculture, forestry and land-use"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_afolu = df.filter(variable='Emissions|CO2|AFOLU').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co_afolu_nn = co2_afolu.applymap(lambda x: - min(x, 0)).reset_index()\n",
+ "co_afolu_nn.variable = 'Emissions|CO2|AFOLU|Net-negative'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co_afolu_nn_df = pyam.IamDataFrame(co_afolu_nn)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.data = df.data.append(co_afolu_nn_df.data, ignore_index=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Determine emissions reductions from land use\n",
+ "\n",
+ "### Where possible, determine AFOLU CO2 emissions reduction relative to baseline"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "base_mapping = df.meta.reset_index()[['model', 'scenario', 'baseline']].groupby(['model'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "afolu_cdr_lst = []\n",
+ "\n",
+ "for mapping in base_mapping:\n",
+ " m = mapping[0]\n",
+ " _df = co_afolu_nn_df.filter(model=m, year=range(2020, 2101))\n",
+ " base_mapping_by_model = mapping[1].groupby(['baseline'])\n",
+ " for _mapping in base_mapping_by_model:\n",
+ " b = _mapping[0]\n",
+ " base = _df.filter(scenario=b).timeseries()\n",
+ " base.index = base.index.droplevel([1, 2, 3, 4])\n",
+ "\n",
+ " for s in _mapping[1].scenario:\n",
+ " cdr = _df.filter(scenario=s).timeseries()\n",
+ " cdr.index = cdr.index.droplevel([1, 2, 3, 4])\n",
+ " cdr = cdr - base\n",
+ " cdr['scenario'] = s\n",
+ " afolu_cdr_lst.append(cdr)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "afolu_cdr = pd.concat(afolu_cdr_lst, sort=False).reset_index()\n",
+ "afolu_cdr['region'] = 'World'\n",
+ "afolu_cdr['variable'] = 'Emissions|CO2|AFOLU|Net-negative reduction'\n",
+ "afolu_cdr['unit'] = 'MtCO2'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "afolu_cdr_df = pyam.IamDataFrame(afolu_cdr)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### For scenarios that do not provide a baseline, use the self-reported land-iuse carbon sequestration timeseries"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "alofu_cdr_direct_df = df.filter(variable='Carbon Sequestration|Land Use',\n",
+ " scenario=['PEP*', 'IMA15*', 'LowEnergyDemand'],\n",
+ " year=range(2020, 2101)\n",
+ " )"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Check that methods 1 and 2 do not overlap, then merge"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if not afolu_cdr_df.meta.index.intersection(alofu_cdr_direct_df.meta.index).empty:\n",
+ " print('There is an overlap of index sets!')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "afolu_cdr_df.data = afolu_cdr_df.data.append(alofu_cdr_direct_df.data, ignore_index=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Remove 'Carbon Sequestration|Land Use' from `IamDataFrame` and merge in alternative metrics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.filter(variable='Carbon Sequestration|Land Use', keep=False, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "df.data = df.data.append(afolu_cdr_df.data, ignore_index=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.rename({'variable': {'Carbon Sequestration|Land Use': 'AFOLU CDR',\n",
+ " 'Emissions|CO2|AFOLU|Net-negative reduction': 'AFOLU CDR'}}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "exclude_no_afolue_cdr = df.require_variable('AFOLU CDR', exclude_on_fail=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.filter(exclude=False, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Rename variables for plots"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "variable_mapping = [\n",
+ " ('Total CDR', [\n",
+ " 'Carbon Sequestration|CCS|Biomass',\n",
+ " 'AFOLU CDR',\n",
+ " 'Carbon Sequestration|Direct Air Capture',\n",
+ " 'Carbon Sequestration|Enhanced Weathering']),\n",
+ " ('AFOLU CDR', 'AFOLU CDR'),\n",
+ " ('BECCS', 'Carbon Sequestration|CCS|Biomass'),\n",
+ " ('Net negative CO2', 'Emissions|CO2|Net-negative'),\n",
+ " ('Compensate CDR', [\n",
+ " 'Carbon Sequestration|CCS|Biomass',\n",
+ " 'AFOLU CDR',\n",
+ " 'Carbon Sequestration|Direct Air Capture',\n",
+ " 'Carbon Sequestration|Enhanced Weathering',\n",
+ " 'Emissions|CO2|Net-negative-negative'])\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "valid_variables = []\n",
+ "for (name, variable) in variable_mapping:\n",
+ " if pyam.isstr(variable):\n",
+ " valid_variables.append(variable)\n",
+ " else:\n",
+ " for v in variable:\n",
+ " valid_variables.append(v)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.filter(variable=valid_variables, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plot by warming category with multiple last years"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def marker_args(m):\n",
+ " return dict(zorder=4,\n",
+ " edgecolors=rc['edgecolors']['marker'][m],\n",
+ " c=rc['c']['marker'][m],\n",
+ " marker=rc['marker']['marker'][m],\n",
+ " linewidths=1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "def boxplot_cumulative_ccs(ymax, last_year, panel_label, legend=True):\n",
+ " fig = plt.figure(figsize=(8, 3))\n",
+ "\n",
+ " _cats = len(cats) - 1\n",
+ " label_list = []\n",
+ "\n",
+ " for i, (name, v) in enumerate(variable_mapping):\n",
+ " _df = df.filter(variable=v, year=range(2020, 2101, 10)).timeseries() / 1000\n",
+ " _df = _df.groupby(['model', 'scenario']).sum()\n",
+ " _df = pd.DataFrame(_df.apply(pyam.cumulative, raw=False, axis=1, first_year=2020, last_year=last_year))\n",
+ " _df = pyam.filter_by_meta(_df, df, category=cats, marker=None, join_meta=True)\n",
+ "\n",
+ " for j, c in enumerate(cats):\n",
+ " __df = _df[_df.category == c]\n",
+ " lst = __df[0][~np.isnan(__df[0])]\n",
+ " pos = 0.5 / _cats * (j - _cats / 2) + i\n",
+ "\n",
+ " outliers = len(lst[lst > ymax])\n",
+ " if outliers > 0:\n",
+ " plt.text(pos - 0.01 * len(cats), ymax * 1.01, outliers)\n",
+ "\n",
+ " p = plt.boxplot(lst, positions=[pos], widths=(0.3 / _cats),\n",
+ " whis='range',\n",
+ " patch_artist=True)\n",
+ " plt.setp(p['boxes'], color=rc['color']['category'][c])\n",
+ " plt.setp(p['medians'], color='black')\n",
+ "\n",
+ " for m in marker:\n",
+ " val = __df.loc[_df.marker == m, 0]\n",
+ " if not val.empty:\n",
+ " plt.scatter(x=pos, y=val, **marker_args(m),\n",
+ " s=40, label=None)\n",
+ "\n",
+ " label_list.append(name)\n",
+ "\n",
+ " for m in marker:\n",
+ " meta = df.filter(marker=m).timeseries()\n",
+ " if not meta.empty:\n",
+ " meta = meta.iloc[0].name[0:2]\n",
+ " plt.scatter(x=[], y=[], **marker_args(m), s=60, label=m)\n",
+ "\n",
+ " for j, c in enumerate(cats):\n",
+ " plt.plot([], c=rc['color']['category'][c], label='{}'.format(c))\n",
+ "\n",
+ " if legend:\n",
+ " plt.legend()\n",
+ "\n",
+ " plt.grid(False)\n",
+ " plt.xlim(-0.6, (i + 0.6))\n",
+ " plt.xticks(range(0, i + 1), label_list)\n",
+ " plt.vlines(x=[_i + 0.5 for _i in range(i)], ymin=0, ymax=ymax, colors='white')\n",
+ " plt.ylim(0, ymax)\n",
+ " plt.ylabel('Cumulative CO2 until {} (GtCO2)'.format(last_year))\n",
+ "\n",
+ " fig.savefig('output/fig2.9{}_cdr_{}.png'.format(panel_label, last_year))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "boxplot_cumulative_ccs(340, 2050, 'a')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "boxplot_cumulative_ccs(1250, 2100, 'b', legend=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Export timeseries data to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.to_excel('output/fig2.9_data_table.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:anaconda]",
+ "language": "python",
+ "name": "conda-env-anaconda-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.4.1_final_energy.ipynb b/assessment/sr15_2.4.1_final_energy.ipynb
new file mode 100644
index 0000000..bad92b2
--- /dev/null
+++ b/assessment/sr15_2.4.1_final_energy.ipynb
@@ -0,0 +1,334 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Final energy demand and carbon intensity analysis\n",
+ "\n",
+ "This notebook contains the scripts to generate **Figure 2.14** showing final energy demand development\n",
+ "and the carbon intensity across scenarios\n",
+ "for the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam\n",
+ "\n",
+ "from utils import boxplot_by_cat"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "all_cats = specs.pop('all_cats')\n",
+ "subcats = specs.pop('subcats')\n",
+ "all_subcats = specs.pop('all_subcats')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2020, 2030, 2050, 2070, 2100]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats, year=years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for filter and plotting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "save_name = 'output/fig2.14{}.{}'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "categories = cats.copy()\n",
+ "categories.remove('Above 2C')\n",
+ "column = 'category'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=sr1p5, category=categories, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotting_args(name, filetype='png', hlines=[]):\n",
+ " return {'categories': categories, 'column': 'category', 'years': years, 'add_marker': marker,\n",
+ " 'hlines': hlines, 'save': save_name.format(name, filetype)}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Development of final energy demand by category"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fe = df.filter(variable='Final Energy').timeseries()\n",
+ "fe.index = fe.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'final_energy'\n",
+ "boxplot_by_cat(pyam.filter_by_meta(fe, **filter_args),\n",
+ " **plotting_args('a_{}'.format(name)),\n",
+ " ylabel='Final Energy (EJ)')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Share of electricity in final demand"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fe_ele = df.filter(variable='Final Energy|Electricity').timeseries()\n",
+ "fe_ele.index = fe_ele.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fe_ele_share = fe_ele / fe * 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'ele_share'\n",
+ "boxplot_by_cat(pyam.filter_by_meta(fe_ele_share, **filter_args),\n",
+ " **plotting_args('b_{}'.format(name)), legend=False,\n",
+ " ylabel='Electricity share in Final Energy (%)')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plot the development of the carbon intensity of eletricity vs. the residual energy demand"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2 = df.filter(variable='Emissions|CO2').timeseries()\n",
+ "co2.index = co2.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_ele = df.filter(variable='Emissions|CO2|Energy|Supply|Electricity').timeseries()\n",
+ "co2_ele.index = co2_ele.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_intensity_ele = co2_ele / fe_ele"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'carbon_intensity_electricity'\n",
+ "boxplot_by_cat(pyam.filter_by_meta(carbon_intensity_ele, **filter_args),\n",
+ " **plotting_args('c_{}'.format(name), hlines=[0]), legend=False,\n",
+ " ylabel='Carbon intensity of electricity (gCO2/MJ)')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_intensity_residual = (co2 - co2_ele) / (fe - fe_ele)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'carbon_intensity_residual'\n",
+ "boxplot_by_cat(pyam.filter_by_meta(carbon_intensity_residual, **filter_args),\n",
+ " **plotting_args('d_{}'.format(name), hlines=[0]), legend=False,\n",
+ " ylabel='Carbon intensity of residual fuel mix (gCO2/MJ)')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:anaconda]",
+ "language": "python",
+ "name": "conda-env-anaconda-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.4.2.1_primary_energy_marker-scenarios.ipynb b/assessment/sr15_2.4.2.1_primary_energy_marker-scenarios.ipynb
new file mode 100644
index 0000000..7d9d586
--- /dev/null
+++ b/assessment/sr15_2.4.2.1_primary_energy_marker-scenarios.ipynb
@@ -0,0 +1,506 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Analysis of the primary energy development
in illustrative pathways\n",
+ "\n",
+ "This notebook computes indicators and diagnostics of the primary-energy timeseries by fuel in **Figure 2.15**, \n",
+ "focusing on the illustrative pathways and the IEA's 'Faster Transition Scenario' using the 'World Energy Model' \n",
+ "in the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "all_cats = specs.pop('all_cats')\n",
+ "subcats = specs.pop('subcats')\n",
+ "all_subcats = specs.pop('all_subcats')\n",
+ "marker = specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2030, 2050, 2100]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats, year=years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for filter and plotting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "save_name = 'output/fig2.15{}.png'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=sr1p5, category=cats, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Retrieve historical data from IEA Energy Statistics and rename variables"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "hist = sr1p5.filter(model='Reference', scenario='IEA Energy Statistics (r2017)')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fossil_vars = [\n",
+ " 'Primary Energy|Coal',\n",
+ " 'Primary Energy|Oil',\n",
+ " 'Primary Energy|Gas'\n",
+ "]\n",
+ "\n",
+ "ren_vars = [\n",
+ " 'Primary Energy|Geothermal',\n",
+ " 'Primary Energy|Hydro',\n",
+ " 'Primary Energy|Ocean',\n",
+ "]\n",
+ "\n",
+ "hist_mapping = {}\n",
+ "\n",
+ "for f in fossil_vars:\n",
+ " hist_mapping.update({f: 'Fossil without CCS'})\n",
+ "for r in ren_vars:\n",
+ " hist_mapping.update({r: 'Other renewables'})\n",
+ "\n",
+ "hist_mapping.update({'Primary Energy|Biomass': 'Biomass without CCS'})\n",
+ "\n",
+ "hist.rename({'variable': hist_mapping}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "hist_args = dict(color='black', linestyle='dashed', linewidth=1)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Add IEA's 'Faster Transition Scenario' to the set of marker scenarios for comparison"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = 'IEA WEM'\n",
+ "col = 'marker'\n",
+ "df.set_meta(m, col,\n",
+ " df.filter(model='IEA World Energy Model 2017',\n",
+ " scenario='Faster Transition Scenario'))\n",
+ "rc.update({'marker': {col: {m: 'o'}},\n",
+ " 'c': {col: {m: 'red'}},\n",
+ " 'edgecolors': {col: {m: 'black'}}}\n",
+ " )\n",
+ "marker += [m]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Rename variables for plots"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "variable_mapping = [\n",
+ " ('Fossil without CCS', 'Primary Energy|Fossil|w/o CCS', 'black'),\n",
+ " ('Fossil with CCS', 'Primary Energy|Fossil|w/ CCS', 'grey'),\n",
+ " ('Biomass without CCS',\n",
+ " ['Primary Energy|Biomass|Modern|w/o CCS',\n",
+ " 'Primary Energy|Biomass|Traditional'], 'forestgreen'),\n",
+ " ('Biomass with CCS', 'Primary Energy|Biomass|Modern|w/ CCS', 'limegreen'),\n",
+ " ('Nuclear', 'Primary Energy|Nuclear', 'firebrick'),\n",
+ " ('Wind', 'Primary Energy|Wind', 'lightskyblue'),\n",
+ " ('Solar', 'Primary Energy|Solar', 'gold'),\n",
+ " ('Other renewables',\n",
+ " ['Primary Energy|Ocean',\n",
+ " 'Primary Energy|Geothermal',\n",
+ " 'Primary Energy|Hydro'], 'darkorange'),\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "variables = []\n",
+ "mapping = {}\n",
+ "\n",
+ "for (name, variable, color) in variable_mapping:\n",
+ " variables.append(name)\n",
+ " if isinstance(variable, list):\n",
+ " for v in variable:\n",
+ " mapping.update({v: name})\n",
+ " else:\n",
+ " mapping.update({variable: name})\n",
+ " rc.update({'color': {'marker': {name: color}}})\n",
+ "\n",
+ "df.rename({'variable': mapping}, inplace=True)\n",
+ "hist.rename({'variable': mapping}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The \"LowEnergyDemand\" scenario by design does not have CCS, and does not explicitly include these variables. Therefore, the variable mapping is implemented differently."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "led_mapping = {\n",
+ " 'Primary Energy|Biomass': 'Biomass without CCS',\n",
+ " 'Primary Energy|Coal': 'Fossil without CCS',\n",
+ " 'Primary Energy|Gas': 'Fossil without CCS',\n",
+ " 'Primary Energy|Oil': 'Fossil without CCS',\n",
+ "}\n",
+ "\n",
+ "df.data = df.data.append(\n",
+ " df.filter(scenario='LowEnergyDemand',\n",
+ " variable=led_mapping)\n",
+ " .rename({'variable': led_mapping})\n",
+ " .data\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.filter(variable=variables, inplace=True)\n",
+ "hist.filter(variable=variables + ['Primary Energy'],\n",
+ " inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plot energy system development by marker scenario"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "w, h = plt.figaspect(0.30)\n",
+ "fig = plt.figure(figsize=(w, h))\n",
+ "ymax = 1150\n",
+ "hist_yr = 2015\n",
+ "\n",
+ "_years = len(years) - 1\n",
+ "label_list = []\n",
+ "\n",
+ "w = 0.5 / len(years)\n",
+ "\n",
+ "for i, m in enumerate(marker):\n",
+ " _df = df.filter(marker=m).timeseries()\n",
+ " meta = _df.iloc[0].name[0:2]\n",
+ " _label = '{}\\n{}\\n({})'.format(meta[0], meta[1], m)\n",
+ " _df.index = _df.index.droplevel([0, 1, 2, 4])\n",
+ " \n",
+ " # use _df.columns because not all scenarios extend until 2100\n",
+ " pos = [0.5 / _years * (j - (len(_df.columns) - 1) / 2) + i\n",
+ " for j in range(len(_df.columns))]\n",
+ " b = [0] * len(_df.columns)\n",
+ "\n",
+ " for v in variables:\n",
+ " if v in _df.index:\n",
+ " lst = _df.loc[v]\n",
+ " plt.bar(x=pos, height=lst, bottom=b, width=w,\n",
+ " color=rc['color']['marker'][v],\n",
+ " edgecolor='black', label=None)\n",
+ " b += _df.loc[v]\n",
+ "\n",
+ " val = (\n",
+ " hist.filter(variable='Primary Energy')\n",
+ " .timeseries()[hist_yr]\n",
+ " )\n",
+ " plt.hlines(y=val, xmin=(-.4 + i),\n",
+ " xmax=(.4 + i), **hist_args,\n",
+ " label=None)\n",
+ " \n",
+ " label_list.append(_label)\n",
+ "\n",
+ " # add years at the top\n",
+ " for j, yr in enumerate(_df.columns):\n",
+ " plt.text(pos[j] - 0.1, ymax * 1.05, yr) \n",
+ " \n",
+ "# add legend entries\n",
+ "plt.hlines(y=[], xmin=[], xmax=[], **hist_args,\n",
+ " label='{} Primary Energy (IEA Energy Statistics 2017)'.format(hist_yr))\n",
+ "for v in variables:\n",
+ " plt.scatter(x=[], y=[], color=rc['color']['marker'][v], label=v)\n",
+ "\n",
+ "plt.legend()\n",
+ "plt.grid(False)\n",
+ "plt.xlim(-0.6, (i + 0.6))\n",
+ "plt.xticks(range(0, i + 1), label_list)\n",
+ "plt.vlines(x=[_i + 0.5 for _i in range(i)], ymin=0, ymax=ymax, colors='white')\n",
+ "plt.ylim(0, ymax)\n",
+ "plt.ylabel('Primary energy by illustrative pathway (EJ/y)')\n",
+ "\n",
+ "fig.savefig(save_name.format('a_primary_energy_by_marker'))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plot energy system development by fuel for all 1.5°C and 2°C pathways"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "w, h = plt.figaspect(0.3)\n",
+ "fig = plt.figure(figsize=(w, h))\n",
+ "ymax = 550\n",
+ "hist_yr = 2015\n",
+ "\n",
+ "_years = len(years) - 1\n",
+ "label_list = []\n",
+ "\n",
+ "def marker_args(m):\n",
+ " return dict(zorder=4,\n",
+ " edgecolors=rc['edgecolors']['marker'][m],\n",
+ " c=rc['c']['marker'][m],\n",
+ " marker=rc['marker']['marker'][m],\n",
+ " linewidths=1)\n",
+ "\n",
+ "for i, v in enumerate(variables):\n",
+ " _df = df.filter(variable=v).timeseries()\n",
+ " _df.index = _df.index.droplevel([2, 3, 4])\n",
+ " _df = pyam.filter_by_meta(_df, df, marker=None, join_meta=True)\n",
+ " \n",
+ " for j, y in enumerate(years):\n",
+ " lst = _df[y][~np.isnan(_df[y])]\n",
+ " pos = 0.5 / _years * (j - _years / 2) + i\n",
+ " \n",
+ " outliers = len(lst[lst > ymax])\n",
+ " if outliers > 0:\n",
+ " plt.text(pos - 0.01 * len(years), ymax * 1.01, outliers)\n",
+ "\n",
+ " p = plt.boxplot(lst, positions=[pos], \n",
+ " whis='range',\n",
+ " patch_artist=True)\n",
+ " plt.setp(p['boxes'], color=rc['color']['marker'][v])\n",
+ " plt.setp(p['medians'], color='black')\n",
+ "\n",
+ " for m in marker:\n",
+ " val = _df.loc[_df.marker == m, y]\n",
+ " if not val.empty:\n",
+ " plt.scatter(x=pos, y=val, **marker_args(m),\n",
+ " s=40, label=None)\n",
+ "\n",
+ " if v in list(hist.variables()):\n",
+ " val = hist.filter(variable=v).timeseries()[hist_yr]\n",
+ " plt.hlines(y=val, xmin=(-.4 + i), xmax=(.4 + i), **hist_args,\n",
+ " label=None)\n",
+ "\n",
+ " label_list.append(v)\n",
+ " \n",
+ "# add legend entries\n",
+ "plt.hlines(y=[], xmin=[], xmax=[], **hist_args,\n",
+ " label='{} Primary Energy (IEA Energy Statistics 2017)'.format(hist_yr))\n",
+ "for m in marker:\n",
+ " meta = df.filter(marker=m).timeseries().iloc[0].name[0:2]\n",
+ " _label = '{}|{} ({})'.format(meta[0], meta[1], m)\n",
+ " plt.scatter(x=[], y=[], **marker_args(m), s=60, label=_label)\n",
+ "\n",
+ "# add years at the top\n",
+ "for _i in range(0, i + 1):\n",
+ " for j, yr in enumerate(years):\n",
+ " plt.text(0.5 / _years * (j - _years / 2) + _i - 0.1,\n",
+ " ymax * 1.05, yr)\n",
+ "\n",
+ "#plt.legend()\n",
+ "plt.grid(False)\n",
+ "plt.xlim(-0.6, (i + 0.6))\n",
+ "plt.xticks(range(0, i + 1), label_list)\n",
+ "plt.vlines(x=[_i + 0.5 for _i in range(i)], ymin=0, ymax=ymax, colors='white')\n",
+ "plt.ylim(0, ymax)\n",
+ "plt.ylabel('Primary energy by fuel type (EJ/y)')\n",
+ "\n",
+ "fig.savefig(save_name.format('b_primary_energy_by_fuel'))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:anaconda]",
+ "language": "python",
+ "name": "conda-env-anaconda-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.4.2.1_primary_energy_statistics.ipynb b/assessment/sr15_2.4.2.1_primary_energy_statistics.ipynb
new file mode 100644
index 0000000..6da5647
--- /dev/null
+++ b/assessment/sr15_2.4.2.1_primary_energy_statistics.ipynb
@@ -0,0 +1,534 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Descriptive statistics of the primary energy development\n",
+ "\n",
+ "This notebook computes indicators and diagnostics of the primary-energy timeseries by fuel\n",
+ "for **Table 2.6** in the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "cats_15 = specs.pop('cats_15')\n",
+ "cats_15_no_lo = specs.pop('cats_15_no_lo')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2020, 2030, 2050]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats_15, year=years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Initialize a `pyam.Statistics` instance"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats = pyam.Statistics(df=df,\n",
+ " filters=[('all 1.5', {}),\n",
+ " ('no/lo os 1.5', {'category': cats_15_no_lo}),\n",
+ " ('hi os 1.5', {'category': ['1.5C high overshoot']})\n",
+ " ], rows=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "header='Primary energy supply (EJ)'\n",
+ "header_share='Share in primary energy (%)'\n",
+ "header_growth='Growth (factor)'\n",
+ "\n",
+ "statistics_settings = dict(\n",
+ " header=header,\n",
+ " header_share=header_share,\n",
+ " header_growth= header_growth,\n",
+ " growth_year=2050,\n",
+ " base_year=2020\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def add_statistics(data, base, row, growth_year, base_year,\n",
+ " header, header_share, header_growth):\n",
+ " stats.add(data, header=header, row=row)\n",
+ " if base is not None:\n",
+ " stats.add(data / base * 100, header=header_share, row=row)\n",
+ " stats.add(data[growth_year] / data[base_year] - 1,\n",
+ " header=header_growth, row=row,\n",
+ " subheader='{}-{}'.format(base_year, growth_year))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Extract primary energy timeseries data and add summary statistics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pe = df.filter(variable='Primary Energy').timeseries()\n",
+ "pe.index = pe.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(pe, None, 'total primary', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Compute share of renewables by various types in primary energy\n",
+ "\n",
+ "Only use scenarios for this indicator that report both biomass and the aggregate non-biomass timeseries - otherwise, the share would be distorted."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### All renewables (biomass and non-biomass)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df_pe_res = df.filter()\n",
+ "df_pe_res.require_variable('Primary Energy|Non-Biomass Renewables', exclude_on_fail=True)\n",
+ "df_pe_res.require_variable('Primary Energy|Biomass', exclude_on_fail=True)\n",
+ "df_pe_res.filter(exclude=False, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "res = (\n",
+ " df_pe_res.filter(variable=['Primary Energy|Biomass', 'Primary Energy|Non-Biomass Renewables'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(res, pe, 'renewables', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Biomass"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "res_bio = (\n",
+ " df.filter(variable=['Primary Energy|Biomass'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(res_bio, pe, 'biomass', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Non-biomass renewables"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "res_non_bio = (\n",
+ " df.filter(variable=['Primary Energy|Non-Biomass Renewables'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(res_non_bio, pe, 'non-biomass', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Renewable energy from wind and solar\n",
+ "\n",
+ "As above, verify that scenarios report values for both 'Wind' and 'Solar' "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df_win_sol = df.filter()\n",
+ "df_win_sol.require_variable('Primary Energy|Wind', exclude_on_fail=True)\n",
+ "df_win_sol.require_variable('Primary Energy|Solar', exclude_on_fail=True)\n",
+ "df_win_sol.filter(exclude=False, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "win_sol = (\n",
+ " df_win_sol.filter(variable=['Primary Energy|Wind',\n",
+ " 'Primary Energy|Solar'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(win_sol, pe, 'wind & solar', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Compute share of nuclear in primary energy"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nuc = (\n",
+ " df.filter(variable=['Primary Energy|Nuclear'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(nuc, pe, 'nuclear', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Compute share of fossil in primary energy"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fossil = (\n",
+ " df.filter(variable=['Primary Energy|Fossil'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(fossil, pe, 'fossil', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coal = (\n",
+ " df.filter(variable=['Primary Energy|Coal'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(coal, pe, 'coal', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "gas = (\n",
+ " df.filter(variable=['Primary Energy|Gas'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(gas, pe, 'gas', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "oil = (\n",
+ " df.filter(variable=['Primary Energy|Oil'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(oil, pe, 'oil', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Display and export summary statistics for all 1.5C scenarios to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "summary = (\n",
+ " stats.summarize(center='median', fullrange=True)\n",
+ " .reindex(columns=['count', header, header_share, header_growth], level=0)\n",
+ ")\n",
+ "summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "summary.to_excel('output/table_2.6_primary_energy_supply.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [default]",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.4.2.2_electricity_generation_marker-scenarios.ipynb b/assessment/sr15_2.4.2.2_electricity_generation_marker-scenarios.ipynb
new file mode 100644
index 0000000..63f247a
--- /dev/null
+++ b/assessment/sr15_2.4.2.2_electricity_generation_marker-scenarios.ipynb
@@ -0,0 +1,492 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Analysis of the electricity generation development
in illustrative pathways\n",
+ "\n",
+ "This notebook computes indicators and diagnostics of the electricity sector and fuel mix timeseries for **Figure 2.16**, \n",
+ "focusing on the illustrative pathways and the IEA's 'Faster Transition Scenario' using the 'World Energy Model' \n",
+ "in the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "all_cats = specs.pop('all_cats')\n",
+ "subcats = specs.pop('subcats')\n",
+ "all_subcats = specs.pop('all_subcats')\n",
+ "marker = specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2030, 2050, 2100]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats, year=years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for filter and plotting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "save_name = 'output/fig2.16{}.png'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=sr1p5, category=cats, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Retrieve historical data from IEA Energy Statistics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "hist = sr1p5.filter(model='Reference', scenario='IEA Energy Statistics (r2017)')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fossil_vars = [\n",
+ " 'Secondary Energy|Electricity|Coal',\n",
+ " 'Secondary Energy|Electricity|Oil',\n",
+ " 'Secondary Energy|Electricityy|Gas'\n",
+ "]\n",
+ "\n",
+ "ren_vars = [\n",
+ " 'Secondary Energy|Electricity|Geothermal',\n",
+ " 'Secondary Energy|Electricity|Hydro',\n",
+ " 'Secondary Energy|Electricity|Ocean',\n",
+ "]\n",
+ "\n",
+ "hist_mapping = {}\n",
+ "\n",
+ "for f in fossil_vars:\n",
+ " hist_mapping.update({f: 'Fossil without CCS'})\n",
+ "for r in ren_vars:\n",
+ " hist_mapping.update({r: 'Other renewables'})\n",
+ "\n",
+ "hist_mapping.update({\n",
+ " 'Secondary Energy|Electricity|Biomass': 'Biomass without CCS'})\n",
+ "\n",
+ "hist.rename({'variable': hist_mapping}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "hist_args = dict(color='black', linestyle='dashed', linewidth=1)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Add IEA's 'Faster Transition Scenario' to the set of marker scenarios for comparison"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = 'IEA WEM'\n",
+ "col = 'marker'\n",
+ "df.set_meta(m, col,\n",
+ " df.filter(model='IEA World Energy Model 2017',\n",
+ " scenario='Faster Transition Scenario'))\n",
+ "rc.update({'marker': {col: {m: 'o'}},\n",
+ " 'c': {col: {m: 'red'}},\n",
+ " 'edgecolors': {col: {m: 'black'}}}\n",
+ " )\n",
+ "marker += [m]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Rename variables for plots"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "variable_mapping = [\n",
+ " ('Fossil without CCS', \n",
+ " ['Secondary Energy|Electricity|Coal|w/o CCS',\n",
+ " 'Secondary Energy|Electricity|Gas|w/o CCS',\n",
+ " 'Secondary Energy|Electricity|Oil|w/o CCS'], 'black'),\n",
+ " ('Fossil with CCS',\n",
+ " ['Secondary Energy|Electricity|Coal|w/ CCS',\n",
+ " 'Secondary Energy|Electricity|Gas|w/ CCS',\n",
+ " 'Secondary Energy|Electricity|Oil|w/ CCS'], 'grey'),\n",
+ " ('Biomass without CCS', 'Secondary Energy|Electricity|Biomass|w/o CCS',\n",
+ " 'forestgreen'),\n",
+ " ('Biomass with CCS', 'Secondary Energy|Electricity|Biomass|w/ CCS',\n",
+ " 'limegreen'),\n",
+ " ('Nuclear', 'Secondary Energy|Electricity|Nuclear', 'firebrick'),\n",
+ " ('Wind', 'Secondary Energy|Electricity|Wind', 'lightskyblue'),\n",
+ " ('Solar', 'Secondary Energy|Electricity|Solar', 'gold'),\n",
+ " ('Other renewables',\n",
+ " ['Secondary Energy|Electricity|Ocean',\n",
+ " 'Secondary Energy|Electricity|Geothermal',\n",
+ " 'Secondary Energy|Electricity|Hydro'], 'darkorange')\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "variables = []\n",
+ "mapping = {}\n",
+ "\n",
+ "for (name, variable, color) in variable_mapping:\n",
+ " variables.append(name)\n",
+ " if isinstance(variable, list):\n",
+ " for v in variable:\n",
+ " mapping.update({v: name})\n",
+ " else:\n",
+ " mapping.update({variable: name})\n",
+ " rc.update({'color': {'marker': {name: color}}})\n",
+ "\n",
+ "df.rename({'variable': mapping}, inplace=True)\n",
+ "hist.rename({'variable': mapping}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.filter(variable=variables, inplace=True)\n",
+ "hist.filter(variable=variables + ['Secondary Energy|Electricity'],\n",
+ " inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plot by marker scenario"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "w, h = plt.figaspect(0.3)\n",
+ "fig = plt.figure(figsize=(w, h))\n",
+ "ymax = 680\n",
+ "hist_yr = 2015\n",
+ "\n",
+ "_years = len(years) - 1\n",
+ "label_list = []\n",
+ "\n",
+ "w = 0.5 / len(years)\n",
+ "\n",
+ "for i, m in enumerate(marker):\n",
+ " _df = df.filter(marker=m).timeseries()\n",
+ " meta = _df.iloc[0].name[0:2]\n",
+ " _label = '{}\\n{}\\n({})'.format(meta[0], meta[1], m)\n",
+ " _df.index = _df.index.droplevel([0, 1, 2, 4])\n",
+ " \n",
+ " # use _df.columns because not all scenarios extend until 2100\n",
+ " pos = [0.5 / _years * (j - (len(_df.columns) - 1) / 2) + i\n",
+ " for j in range(len(_df.columns))]\n",
+ " b = [0] * len(_df.columns)\n",
+ "\n",
+ " for v in variables:\n",
+ " if v in _df.index:\n",
+ " lst = _df.loc[v]\n",
+ " plt.bar(x=pos, height=lst, bottom=b, width=w,\n",
+ " color=rc['color']['marker'][v],\n",
+ " edgecolor='black', label=None)\n",
+ " b += _df.loc[v]\n",
+ "\n",
+ " label_list.append(_label)\n",
+ "\n",
+ " val = (\n",
+ " hist.filter(variable='Secondary Energy|Electricity')\n",
+ " .timeseries()[hist_yr]\n",
+ " )\n",
+ " plt.hlines(y=val, xmin=(-.4 + i),\n",
+ " xmax=(.4 + i), **hist_args,\n",
+ " label=None)\n",
+ "\n",
+ " # add years at the top\n",
+ " for j, yr in enumerate(_df.columns):\n",
+ " plt.text(pos[j] - 0.1, ymax * 1.05, yr) \n",
+ " \n",
+ "# add legend entries\n",
+ "plt.hlines(y=[], xmin=[], xmax=[], **hist_args,\n",
+ " label='{} Electricity Generation (IEA Energy Statistics 2017)'.format(hist_yr))\n",
+ "for v in variables:\n",
+ " plt.scatter(x=[], y=[], color=rc['color']['marker'][v], label=v)\n",
+ "\n",
+ "plt.legend()\n",
+ "plt.grid(False)\n",
+ "plt.xlim(-0.5, (i + 0.6))\n",
+ "plt.xticks(range(0, i + 1), label_list)\n",
+ "plt.vlines(x=[_i + 0.5 for _i in range(i)], ymin=0, ymax=ymax, colors='white')\n",
+ "plt.ylim(0, ymax)\n",
+ "plt.ylabel('Electricity generation by illustrative pathway (EJ/y)')\n",
+ "\n",
+ "fig.savefig(save_name.format('a_electricity_generation_by_marker'))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plot electricity system development by fuel for all 1.5°C and 2°C pathways"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "w, h = plt.figaspect(0.3)\n",
+ "fig = plt.figure(figsize=(w, h))\n",
+ "ymax = 320\n",
+ "hist_yr = 2015\n",
+ "\n",
+ "_years = len(years) - 1\n",
+ "label_list = []\n",
+ "\n",
+ "def marker_args(m):\n",
+ " return dict(zorder=4,\n",
+ " edgecolors=rc['edgecolors']['marker'][m],\n",
+ " c=rc['c']['marker'][m],\n",
+ " marker=rc['marker']['marker'][m],\n",
+ " linewidths=1)\n",
+ "\n",
+ "for i, v in enumerate(variables):\n",
+ " _df = df.filter(variable=v).timeseries()\n",
+ " _df.index = _df.index.droplevel([2, 3, 4])\n",
+ " _df = pyam.filter_by_meta(_df, df, marker=None, join_meta=True)\n",
+ " \n",
+ " for j, y in enumerate(years):\n",
+ " lst = _df[y][~np.isnan(_df[y])]\n",
+ " pos = 0.5 / _years * (j - _years / 2) + i\n",
+ " \n",
+ " outliers = len(lst[lst > ymax])\n",
+ " if outliers > 0:\n",
+ " plt.text(pos - 0.01 * len(years), ymax * 1.01, outliers)\n",
+ "\n",
+ " p = plt.boxplot(lst, positions=[pos],\n",
+ " whis='range',\n",
+ " patch_artist=True)\n",
+ " plt.setp(p['boxes'], color=rc['color']['marker'][v])\n",
+ " plt.setp(p['medians'], color='black')\n",
+ " \n",
+ " for m in marker:\n",
+ " val = _df.loc[_df.marker == m, y]\n",
+ " if not val.empty:\n",
+ " plt.scatter(x=pos, y=val, **marker_args(m),\n",
+ " s=40, label=None)\n",
+ "\n",
+ " if v in list(hist.variables()):\n",
+ " val = hist.filter(variable=v).timeseries()[hist_yr]\n",
+ " plt.hlines(y=val, xmin=(-.4 + i), xmax=(.4 + i), **hist_args,\n",
+ " label=None)\n",
+ " \n",
+ " label_list.append(v)\n",
+ "\n",
+ "# add legend entries\n",
+ "plt.hlines(y=[], xmin=[], xmax=[], **hist_args,\n",
+ " label='{} Electricity Generation (IEA Energy Statistics 2017)'.format(hist_yr))\n",
+ "for m in marker:\n",
+ " meta = df.filter(marker=m).timeseries().iloc[0].name[0:2]\n",
+ " _label = '{}|{} ({})'.format(meta[0], meta[1], m)\n",
+ " plt.scatter(x=[], y=[], **marker_args(m), s=60, label=_label)\n",
+ "\n",
+ "# add years at the top\n",
+ "for _i in range(0, i + 1):\n",
+ " for j, yr in enumerate(years):\n",
+ " plt.text(0.5 / _years * (j - _years / 2) + _i - 0.1,\n",
+ " ymax * 1.05, yr)\n",
+ "\n",
+ "# plt.legend()\n",
+ "plt.grid(False)\n",
+ "plt.xlim(-0.6, (i + 0.6))\n",
+ "plt.xticks(range(0, i + 1), label_list)\n",
+ "plt.vlines(x=[_i + 0.5 for _i in range(i)], ymin=0, ymax=ymax, colors='white')\n",
+ "plt.ylim(0, ymax)\n",
+ "plt.ylabel('Electricity generation by fuel type (EJ/y)')\n",
+ "\n",
+ "fig.savefig(save_name.format('b_electricity_generation_by_fuel'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:anaconda]",
+ "language": "python",
+ "name": "conda-env-anaconda-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.4.2.2_electricity_generation_statistics.ipynb b/assessment/sr15_2.4.2.2_electricity_generation_statistics.ipynb
new file mode 100644
index 0000000..6dc5f55
--- /dev/null
+++ b/assessment/sr15_2.4.2.2_electricity_generation_statistics.ipynb
@@ -0,0 +1,550 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Descriptive statistics of electricity generation\n",
+ "\n",
+ "This notebook computes indicators and diagnostics of the primary-energy timeseries by fuel\n",
+ "for **Table 2.7** in the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "cats_15 = specs.pop('cats_15')\n",
+ "cats_15_no_lo = specs.pop('cats_15_no_lo')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2020, 2030, 2050]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats_15, year=years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Initialize a `pyam.Statistics` instance"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats = pyam.Statistics(df=df,\n",
+ " filters=[('all 1.5', {}),\n",
+ " ('no/lo os 1.5', {'category': cats_15_no_lo}),\n",
+ " ('hi os 1.5', {'category': ['1.5C high overshoot']})\n",
+ " ], rows=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "header='Electricity generation (EJ)'\n",
+ "header_share='Share in electricity generation (%)'\n",
+ "header_growth='Growth (factor)'\n",
+ "\n",
+ "statistics_settings = dict(\n",
+ " header=header,\n",
+ " header_share='Share in electricity generation (%)',\n",
+ " header_growth='Growth (factor)',\n",
+ " growth_year=2050,\n",
+ " base_year=2020\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def add_statistics(data, base, row, growth_year, base_year,\n",
+ " header, header_share, header_growth):\n",
+ " stats.add(data, header=header, row=row)\n",
+ " if base is not None:\n",
+ " stats.add(data / base * 100, header=header_share, row=row)\n",
+ " stats.add(data[growth_year] / data[base_year] - 1,\n",
+ " header=header_growth, row=row,\n",
+ " subheader='{}-{}'.format(base_year, growth_year))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Extract total electricity generation timeseries and add summary statistics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "se = df.filter(variable='Secondary Energy|Electricity').timeseries()\n",
+ "se.index = se.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(se, None, 'total generation', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Compute share of renewables by various types in electricity generation\n",
+ "\n",
+ "Only use scenarios for this indicator that report both biomass and the aggregate non-biomass timeseries - otherwise, the share would be distorted."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### All renewables (biomass and non-biomass)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df_pe_res = df.filter()\n",
+ "df_pe_res.require_variable('Secondary Energy|Electricity|Non-Biomass Renewables', exclude_on_fail=True)\n",
+ "df_pe_res.require_variable('Secondary Energy|Electricity|Biomass', exclude_on_fail=True)\n",
+ "df_pe_res.filter(exclude=False, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "res = (\n",
+ " df_pe_res.filter(variable=['Secondary Energy|Electricity|Biomass',\n",
+ " 'Secondary Energy|Electricity|Non-Biomass Renewables'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(res, se, 'renewables', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Biomass"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "res_bio = (\n",
+ " df_pe_res.filter(variable=['Secondary Energy|Electricity|Biomass'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(res_bio, se, 'biomass', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Non-biomass renewables"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "res_non_bio = (\n",
+ " df_pe_res.filter(variable=['Secondary Energy|Electricity|Non-Biomass Renewables'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(res_non_bio, se, 'non-biomass', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Renewable energy from wind and solar\n",
+ "\n",
+ "As above, verify that scenarios report values for both 'Wind' and 'Solar' "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df_win_sol = df.filter()\n",
+ "df_win_sol.require_variable('Secondary Energy|Electricity|Solar', exclude_on_fail=True)\n",
+ "df_win_sol.require_variable('Secondary Energy|Electricity|Wind', exclude_on_fail=True)\n",
+ "df_win_sol.filter(exclude=False, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "win_sol = (\n",
+ " df_win_sol.filter(variable=['Secondary Energy|Electricity|Solar',\n",
+ " 'Secondary Energy|Electricity|Wind '])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(win_sol, se, 'wind & solar', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Compute share of nuclear in electricity generation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nuc = (\n",
+ " df.filter(variable=['Secondary Energy|Electricity|Nuclear'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(nuc, se, 'nuclear', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Compute share of fossil in electricity generation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df_fossil = df.filter()\n",
+ "df_fossil.require_variable('Secondary Energy|Electricity|Coal', exclude_on_fail=True)\n",
+ "df_fossil.require_variable('Secondary Energy|Electricity|Gas', exclude_on_fail=True)\n",
+ "df_fossil.require_variable('Secondary Energy|Electricity|Oil', exclude_on_fail=True)\n",
+ "df_fossil.filter(exclude=False, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fossil = (\n",
+ " df.filter(variable=['Secondary Energy|Electricity|Coal',\n",
+ " 'Secondary Energy|Electricity|Gas',\n",
+ " 'Secondary Energy|Electricity|Oil'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(fossil, se, 'fossil', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coal = (\n",
+ " df_fossil.filter(variable=['Secondary Energy|Electricity|Coal'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(coal, se, 'coal', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "gas = (\n",
+ " df_fossil.filter(variable=['Secondary Energy|Electricity|Gas'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(gas, se, 'gas', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "oil = (\n",
+ " df_fossil.filter(variable=['Secondary Energy|Electricity|Oil'])\n",
+ " .timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "add_statistics(oil, se, 'oil', **statistics_settings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Display and export summary statistics for all 1.5°C pathways to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "summary = (\n",
+ " stats.summarize(center='median', fullrange=True)\n",
+ " .reindex(columns=['count', header, header_share, header_growth], level=0)\n",
+ ")\n",
+ "summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "summary.to_excel('output/table_2.7_electricity_generation.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [default]",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.4.2.3_ccs_deployment.ipynb b/assessment/sr15_2.4.2.3_ccs_deployment.ipynb
new file mode 100644
index 0000000..0e3e1e7
--- /dev/null
+++ b/assessment/sr15_2.4.2.3_ccs_deployment.ipynb
@@ -0,0 +1,343 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Analysis of carbon capture and sequestration (CCS)\n",
+ "\n",
+ "This notebook computes indicators and diagnostics of the deployment of CCS by fuel\n",
+ "and the total amount of CO2 stored as shown in **Figure 2.17**\n",
+ "in the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "%matplotlib inline\n",
+ "import pyam\n",
+ "\n",
+ "from utils import boxplot_by_cat"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "all_cats = specs.pop('all_cats')\n",
+ "subcats = specs.pop('subcats')\n",
+ "all_subcats = specs.pop('all_subcats')\n",
+ "plotting_args = specs.pop('plotting_args')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment\n",
+ "\n",
+ "Use all years (as of 2020) to correctly compute the total amount of CO2 stored in each scenario."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = range(2020, 2101, 5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats, year=years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for filter and plotting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_ylabel = '{} with CCS (EJ)'\n",
+ "save_name = 'output/fig2.17{}.{}'\n",
+ "figure_format = 'png'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=sr1p5, category=cats, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotting_args(name, panel_label=None, filetype=figure_format):\n",
+ " return {'categories': cats, 'column': 'category', 'years': range(2020, 2101, 10), 'add_marker': marker,\n",
+ " 'ylabel': plot_ylabel.format(name),\n",
+ " 'save': save_name.format(name if panel_label is None else '{}_{}'.format(panel_label, name), filetype)}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Add IEA's 'Faster Transition Scenario' to the set of marker scenarios for comparison"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = 'IEA WEM'\n",
+ "col = 'marker'\n",
+ "sr1p5.set_meta(m, col,\n",
+ " sr1p5.filter(model='IEA World Energy Model 2017',\n",
+ " scenario='Faster Transition Scenario'))\n",
+ "rc.update({'marker': {col: {m: 'o'}},\n",
+ " 'c': {col: {m: 'red'}},\n",
+ " 'edgecolors': {col: {m: 'black'}}}\n",
+ " )\n",
+ "marker += [m]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Extract CCS timeseries data by fuel"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ccs_bio = df.filter(variable='Primary Energy|Biomass|Modern|w/ CCS').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'bioenergy'\n",
+ "fig = boxplot_by_cat(\n",
+ " pyam.filter_by_meta(ccs_bio, **filter_args),\n",
+ " **plotting_args(name, 'a'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ccs_coal = df.filter(variable='Primary Energy|Coal|w/ CCS').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'coal'\n",
+ "boxplot_by_cat(\n",
+ " pyam.filter_by_meta(ccs_coal, **filter_args),\n",
+ " **plotting_args(name, 'b'), legend=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ccs_gas = df.filter(variable='Primary Energy|Gas|w/ CCS').timeseries()\n",
+ "ccs_gas.index = ccs_gas.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'gas'\n",
+ "boxplot_by_cat(\n",
+ " pyam.filter_by_meta(ccs_gas, **filter_args),\n",
+ " **plotting_args(name, 'c'), legend=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Compute cumulative CO2 stored"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ccs = (\n",
+ " df.filter(variable='Carbon Sequestration|CCS')\n",
+ " .convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cum_ccs = pd.DataFrame()\n",
+ "for i in range(2020, 2100, 10):\n",
+ " cum_ccs[i] = ccs.apply(pyam.cumulative, raw=False, axis=1, first_year=2020, last_year=i)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "boxplot_by_cat(\n",
+ " pyam.filter_by_meta(cum_ccs, **filter_args),\n",
+ " categories=cats, column='category', years=range(2020, 2100, 10),\n",
+ " ylabel='cumulative CO2 stored (Gt)',\n",
+ " save=save_name.format('d_cumulative_ccs', figure_format),\n",
+ " ymax=2050, add_marker=marker, legend=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:anaconda]",
+ "language": "python",
+ "name": "conda-env-anaconda-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.4.4_afolu_emissions.ipynb b/assessment/sr15_2.4.4_afolu_emissions.ipynb
new file mode 100644
index 0000000..75c1e67
--- /dev/null
+++ b/assessment/sr15_2.4.4_afolu_emissions.ipynb
@@ -0,0 +1,323 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Analysis of non-CO2 emissions from agriculture, forestry and land use\n",
+ "\n",
+ "This notebook plots figures for emissions of CH4 and N2O from the land use sector\n",
+ "for **Figure 2.25** of the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "import pyam\n",
+ "\n",
+ "from utils import boxplot_by_cat"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must be generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "all_cats = specs.pop('all_cats')\n",
+ "subcats = specs.pop('subcats')\n",
+ "all_subcats = specs.pop('all_subcats')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2010, 2030, 2050, 2100]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.meta.rename(columns={'Kyoto-GHG|2010 (SAR)': 'kyoto_ghg_2010'}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(kyoto_ghg_2010='in range', category=cats, year=years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for filter and plotting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_ylabel = 'Global {} emissions from AFOLU ({})'\n",
+ "save_name = 'output/fig2.25{}.{}'\n",
+ "data_header = 'Emissions from AFOLU'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=sr1p5, category=cats, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotting_args(name, label, unit, panel_label=None, filetype='png'):\n",
+ " return {'categories': cats, 'column': 'category', 'years': years,\n",
+ " 'add_marker': marker,\n",
+ " 'ylabel': plot_ylabel.format(label, unit),\n",
+ " 'save': save_name.format(name if panel_label is None else '{}_{}'.format(panel_label, name), filetype)}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = []"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Methane emissions from agriculture"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ch4_afolu = df.filter(variable='Emissions|CH4|AFOLU').timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "name = 'ch4_afolu'\n",
+ "species = 'CH4'\n",
+ "unit = 'MtCH4/yr'\n",
+ "\n",
+ "_data = pyam.filter_by_meta(ch4_afolu, **filter_args)\n",
+ "boxplot_by_cat(_data, **plotting_args(name, species, unit, 'a'))\n",
+ "_data['species'] = species\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Nitrous oxide emissions from agriculture"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "n2o_afolu = (\n",
+ " df.filter(variable='Emissions|N2O|AFOLU')\n",
+ " .convert_unit({'kt N2O/yr': ('Mt N2O/yr', 0.001)})\n",
+ " .timeseries()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = 'no2_afolu'\n",
+ "species = 'N2O'\n",
+ "unit = 'MtN2O'\n",
+ "\n",
+ "_data = pyam.filter_by_meta(n2o_afolu, **filter_args)\n",
+ "fig = boxplot_by_cat(_data, **plotting_args(name, species, unit, 'b'),\n",
+ " legend=False)\n",
+ "_data['species'] = species\n",
+ "data.append(_data)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Export timeseries data to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = pd.concat(data).set_index(['species', 'category', 'marker'], append=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data.reset_index().to_excel('output/fig2.25_data_table.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:anaconda]",
+ "language": "python",
+ "name": "conda-env-anaconda-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_2.5_carbon_price_analysis.ipynb b/assessment/sr15_2.5_carbon_price_analysis.ipynb
new file mode 100644
index 0000000..06ce2d6
--- /dev/null
+++ b/assessment/sr15_2.5_carbon_price_analysis.ipynb
@@ -0,0 +1,887 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Assessment of carbon prices by warming category\n",
+ "\n",
+ "This notebook contains the carbon price assessment of the scenario ensemble \n",
+ "in **Section 2.5.2** and for **Figure 2.26** of the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load `pyam` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import io\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('style_sr15.mplstyle')\n",
+ "%matplotlib inline\n",
+ "\n",
+ "import pyam\n",
+ "from utils import boxplot_by_cat"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must have been generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Downselect scenario ensemble to categories of interest for this assessment\n",
+ "\n",
+ "Only scenarios that limit warming to at most 2°C at the end of the century are included in this assessment."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Set specifications for figures and statistics\n",
+ "\n",
+ "First, set the list of years included in the plots. Then, define an auxiliary dictionary and function for easier display."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2030, 2050, 2070, 2100]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filter_args = dict(df=sr1p5, category=cats, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotting_args():\n",
+ " return {'categories': cats, 'column': 'category',\n",
+ " 'add_marker': marker, 'ar5_format': True}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Rename aggregate indicator from metadata\n",
+ "\n",
+ "This simplifies including the aggregate indicator 'Annual compounded Net Present Value' in the plots and assessment below."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.meta.rename(columns={'carbon price|AC NPV (2030-2100)': 'ac_npv'}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Check for misreported carbon prices and exclude these from analysis and figues\n",
+ "\n",
+ "In some cases, models were not able to report carbon prices throughout the century due to the scenario protocol and policy implementation. Carbon prices below 5 USD/tCO2 in 2030 or reported as `nan` were, after consultation with the modeling teams, assessed to be misreported entries. For consistency, these scenarios are excluded throughout this notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats, variable='Price|Carbon', year=range(2030, 2101, 10))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "misc = df.validate({'Price|Carbon': {'lo': 5, 'year': 2030}},\n",
+ " exclude_on_fail=True).set_index(pyam.META_IDX)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Check for `nan` entries in the carbon price timeseries and remove scenarios."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price = df.timeseries()\n",
+ "carbon_price.index = carbon_price.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "has_na = carbon_price.apply(lambda x: np.isnan(max(x)), axis=1)\n",
+ "na = carbon_price[has_na]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.set_meta(meta=True, name='exclude', index=na.index)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Show all carbon-price trajectories excluded from the analysis and export to `xlsx` for archiving"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "all_excluded = carbon_price.loc[misc.index].append(na)\n",
+ "all_excluded"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.set_meta(True, 'exclude', all_excluded.index)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.filter(exclude=False, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Compute net-present value carbon price timeseries\n",
+ "\n",
+ "Reload carbon-price timeseries after excluding non-valid timeseries data."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price = df.timeseries()\n",
+ "carbon_price.index = carbon_price.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price_npv = carbon_price.copy()\n",
+ "\n",
+ "r = 0.05\n",
+ "baseyear = 2020\n",
+ "\n",
+ "for y in carbon_price_npv.columns: \n",
+ " carbon_price_npv[y] = carbon_price_npv[y] / math.pow(1 + r, y - baseyear)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statistical assessment of the carbon price development\n",
+ "\n",
+ "The following assessment is the basis of *Section 2.5.2.1*."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats = pyam.Statistics(df=sr1p5, groupby={'category': cats})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats.add(carbon_price, header='Carbon price')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "summary = stats.summarize()\n",
+ "summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "summary.to_excel('output/sec_2.5_carbon_price_summary_statistics.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Descriptive statistics of the 'Higher 2C' pathways"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stats.summarize().loc[('category', 'Higher 2C')]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Descriptive statistics of the 'Below 1.5C' pathways"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "stats.summarize().loc[('category', 'Below 1.5C')]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plot the average carbon price by category\n",
+ "\n",
+ "This section produces panel b of **Figure 2.26**."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filtered_npv = pyam.filter_by_meta(carbon_price_npv, df, category=None, marker=None, ac_npv=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "price_threshold = 690\n",
+ "cols = ['ac_npv']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "boxplot_by_cat(filtered_npv, **plotting_args(), years=cols,\n",
+ " xlabel='Annual compounded net-present-value carbon price from 2030 until 2100',\n",
+ " ylabel='Price of carbon (USD/tCO2)',\n",
+ " ymax=price_threshold, ymin=0, save='output/fig2.26b_carbon_price_npv.png')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Summary of outliers in the figure\n",
+ "\n",
+ "Display the timeseries data of scenarios exceeding the upper threshold of the figure (the number of data points exceeding the threshold per category is marked above the panel)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "above_threshold = filtered_npv[cols].apply(lambda x: max(x) > price_threshold, axis=1)\n",
+ "filtered_npv[above_threshold]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plot price trajectory by category over time using a log scale\n",
+ "\n",
+ "This section produces panel a of **Figure 2.26**."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filtered_data = pyam.filter_by_meta(carbon_price, df, category=None, marker=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "price_threshold = 15000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "hlines = (\n",
+ " [i for i in range(10, 91, 10)] \n",
+ " + [i for i in range(100, 901, 100)]\n",
+ " + [i for i in range(1000, 10001, 1000)]\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "boxplot_by_cat(filtered_data, **plotting_args(), ylabel='Price of carbon (USD/tCO2)',\n",
+ " log_scale=True, years=years, ymax=price_threshold,\n",
+ " hlines=hlines, legend=False, save='output/fig2.26a_carbon_price_over_time.png')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Summary of outliers in the figure\n",
+ "\n",
+ "Display the timeseries data of scenarios exceeding the upper threshold of the figure (the number of data points exceeding the threshold per category is marked above the panel)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "above_threshold = filtered_data[years].apply(lambda x: max(x) > price_threshold, axis=1)\n",
+ "filtered_data[above_threshold]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Export timeseries data to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "writer = pd.ExcelWriter('output/sec2.5_carbon_price_timeseries.xlsx')\n",
+ "pyam.utils.write_sheet(writer, 'real', pyam.filter_by_meta(carbon_price, **filter_args),\n",
+ " index=True)\n",
+ "pyam.utils.write_sheet(writer, 'npv', pyam.filter_by_meta(carbon_price_npv, **filter_args),\n",
+ " index=True)\n",
+ "writer.save()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Assessment of relative difference between 1.5°C and 2°C scenarios\n",
+ "\n",
+ "The following assessment is the basis of *Section 2.5.2.1*.\n",
+ "\n",
+ "We first define a mapping between corresponding pairs of scenarios, then assign this mapping to a number of dictionaries."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mapping = [\n",
+ " ('SSP1-19', 'SSP1-26', 'SSP1'),\n",
+ " ('SSP2-19', 'SSP2-26', 'SSP2'),\n",
+ " ('SSP5-19', 'SSP5-26', 'SSP5'),\n",
+ " ('ADVANCE_2020_1.5C-2100', 'ADVANCE_2020_WB2C', 'ADVANCE_2020'),\n",
+ " ('CD-LINKS_NPi2020_400', 'CD-LINKS_NPi2020_1000', 'CD-LINKS_NPi2020'),\n",
+ " ('DAC15_50', 'DAC2_66', 'DAC'),\n",
+ " ('EMF33_1.5C_full', 'EMF33_WB2C_full', 'EMF33_full'),\n",
+ " ('EMF33_1.5C_limbio', 'EMF33_WB2C_limbio', 'EMF33_limbio'),\n",
+ " ('EMF33_1.5C_nofuel', 'EMF33_WB2C_nofuel', 'EMF33_nofuel'),\n",
+ " ('PEP_1p5C_full_eff', 'PEP_2C_full_eff', 'PEP_full_eff'),\n",
+ " ('PEP_1p5C_full_goodpractice', 'PEP_2C_full_goodpractice', 'PEP_full_goodpractice'),\n",
+ " ('PEP_1p5C_full_NDC', 'PEP_2C_full_NDC', 'PEP_full_NDC'),\n",
+ " ('PEP_1p5C_full_netzero', 'PEP_2C_full_netzero', 'PEP_full_netzero'),\n",
+ " ('PEP_1p5C_red_eff', 'PEP_2C_red_eff', 'PEP_red_eff'),\n",
+ " ('SMP_1p5C_Def', 'SMP_2C_Def', 'SMP_Def'),\n",
+ " ('SMP_1p5C_early', 'SMP_2C_early', 'SMP_early'),\n",
+ " ('SMP_1p5C_lifesty', 'SMP_2C_lifesty', 'SMP_lifesty'),\n",
+ " ('SMP_1p5C_regul', 'SMP_2C_regul', 'SMP_regul'),\n",
+ " ('SMP_1p5C_Sust', 'SMP_2C_Sust', 'SMP_Sust'),\n",
+ " ('SFCM_SSP2_Bio_1p5Degree', 'SFCM_SSP2_Bio_2Degree', 'SFCM_SSP2_Bio'),\n",
+ " ('SFCM_SSP2_combined_1p5Degree', 'SFCM_SSP2_combined_2Degree', 'SFCM_SSP2_combined'),\n",
+ " ('SFCM_SSP2_EEEI_1p5Degree', 'SFCM_SSP2_EEEI_2Degree', 'SFCM_SSP2_EEEI'),\n",
+ " ('SFCM_SSP2_LifeStyle_1p5Degree', 'SFCM_SSP2_LifeStyle_2Degree', 'SFCM_SSP2_LifeStyle'),\n",
+ " ('SFCM_SSP2_Ref_1p5Degree', 'SFCM_SSP2_Ref_2Degree', 'SFCM_SSP2_Ref'),\n",
+ " ('SFCM_SSP2_ST_bio_1p5Degree', 'SFCM_SSP2_ST_bio_2Degree', 'SFCM_SSP2_ST_bio'),\n",
+ " ('SFCM_SSP2_ST_CCS_1p5Degree', 'SFCM_SSP2_ST_CCS_2Degree', 'SFCM_SSP2_ST_CCS'),\n",
+ " ('SFCM_SSP2_ST_nuclear_1p5Degree', 'SFCM_SSP2_ST_nuclear_2Degree', 'SFCM_SSP2_ST_nuclear'),\n",
+ " ('SFCM_SSP2_ST_solar_1p5Degree', 'SFCM_SSP2_ST_solar_2Degree', 'SFCM_SSP2_ST_solar'),\n",
+ " ('SFCM_SSP2_ST_wind_1p5Degree', 'SFCM_SSP2_ST_wind_2Degree', 'SFCM_SSP2_ST_wind'),\n",
+ " ('SFCM_SSP2_SupTech_1p5Degree', 'SFCM_SSP2_SupTech_2Degree', 'SFCM_SSP2_SupTech'),\n",
+ " ('TERL_15D_LowCarbonTransportPolicy', 'TERL_2D_LowCarbonTransportPolicy', 'TERL_LowCarbonTransportPolicy'),\n",
+ " ('TERL_15D_NoTransportPolicy', 'TERL_2D_NoTransportPolicy', 'TERL_NoTransportPolicy')\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "rename_1p5 = {}\n",
+ "rename_1p5_reverse = {}\n",
+ "rename_2 = {}\n",
+ "rename_2_reverse = {}\n",
+ "\n",
+ "for (scen_1p5, scen_2, scen) in mapping:\n",
+ " rename_1p5[scen_1p5] = scen\n",
+ " rename_1p5_reverse[scen] = scen_1p5\n",
+ " rename_2[scen_2] = scen\n",
+ " rename_2_reverse[scen] = scen_2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def apply_rename_mapping(data, rename):\n",
+ " return data.loc[(slice(None), rename), :].copy().rename(rename, level=1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price_all = df.filter(variable='Price|Carbon', exclude=False,\n",
+ " year=range(2030, 2101, 10)).timeseries()\n",
+ "carbon_price_all = pyam.filter_by_meta(carbon_price_all, sr1p5, ac_npv=None, join_meta=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price_1p5 = apply_rename_mapping(carbon_price_all, rename_1p5)\n",
+ "carbon_price_2 = apply_rename_mapping(carbon_price_all, rename_2)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Show pairs where only one of the corresponding scenario is available\n",
+ "\n",
+ "The reason for the corresponding scenario not being available could be one of the following:\n",
+ " - not reported by modeling team\n",
+ " - excluded due misreported carbon prices (see section above)\n",
+ " - warming outcome not in line with comparison of 1.5°C and 2°C scenarios"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pd.DataFrame(index=carbon_price_1p5.index.difference(carbon_price_2.index))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pd.DataFrame(index=carbon_price_2.index.difference(carbon_price_1p5.index))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Compute the relative difference per scenario pair over time"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price_rel = carbon_price_1p5 / carbon_price_2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Remove scenarios where the relative difference is not defined"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price_rel = carbon_price_rel[~np.isnan(carbon_price_rel[2030])]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Define an auxiliary function to generate descriptive statistics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def describe_by_cat(data, category=None):\n",
+ " return (\n",
+ " apply_rename_mapping(\n",
+ " pyam.filter_by_meta(apply_rename_mapping(data, rename_1p5_reverse),\n",
+ " sr1p5, category=category),\n",
+ " rename_1p5)\n",
+ " .describe()\n",
+ " .reindex(index=['count', 'mean', '25%', '75%'])\n",
+ " )"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Show the descriptive statistics across corresponding scenario paris\n",
+ "\n",
+ "#### Across all scenario pairs where the lower scenario of the pair is in a 1.5°C category"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "describe_by_cat(carbon_price_rel, ['Below 1.5C', '1.5C low overshoot', '1.5C high overshoot'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Show the descriptive statistics across scenario pairs excluding high overshoot scebaruis"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "describe_by_cat(carbon_price_rel, ['Below 1.5C', '1.5C low overshoot'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Descriptive statistics only for scenarios submitted from model intercomparison projects"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "projects = ['ADVANCE*', 'SSP*', 'CD-LINKS*', 'EMF33*']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price_rel_mip = (\n",
+ " carbon_price_rel[pyam.pattern_match(carbon_price_rel.reset_index().scenario, projects).values]\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Descriptive statistics across all scenario pairs"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "describe_by_cat(carbon_price_rel_mip, ['Below 1.5C', '1.5C low overshoot', '1.5C high overshoot'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Only scenarios that remain below 1.5°C or exhibit low overshoot"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "describe_by_cat(carbon_price_rel_mip, ['Below 1.5C', '1.5C low overshoot'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Export data for relative carbon price assessment to `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def add_cats(data, df, col_suffix, mapping, mapping_reverse):\n",
+ " ret = apply_rename_mapping(data, mapping_reverse)\n",
+ " ret['scenario_{}'.format(col_suffix)] = ret.reset_index().scenario.values\n",
+ " ret = pyam.filter_by_meta(ret, df, category=None, join_meta=True)\n",
+ " ret.rename(columns={'category': 'subcategory_{}'.format(col_suffix)}, inplace=True)\n",
+ " return apply_rename_mapping(ret, mapping)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price_rel = add_cats(carbon_price_rel, df, '1.5', rename_1p5, rename_1p5_reverse)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price_rel = add_cats(carbon_price_rel, df, '2', rename_2, rename_2_reverse)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "carbon_price_rel.to_excel('output/sec2.5_relative_carbon_prices.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [default]",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/sr15_4.2_sectoral_indicators.ipynb b/assessment/sr15_4.2_sectoral_indicators.ipynb
new file mode 100644
index 0000000..687ce29
--- /dev/null
+++ b/assessment/sr15_4.2_sectoral_indicators.ipynb
@@ -0,0 +1,394 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *IPCC SR15 scenario assessment*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Indicators of the pace of transformation
in 1.5°C pathways and selected sectoral studies\n",
+ "\n",
+ "This notebook computes indicators of sectoral transformation for comparison to specialized studies\n",
+ "in Chapter 4 of the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario data used in this analysis can be accessed and downloaded at [https://data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load ``pyam`` package and other dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "%matplotlib inline\n",
+ "import pyam"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import scenario data, categorization and specifications files\n",
+ "\n",
+ "The metadata file must have been generated from the notebook `sr15_2.0_categories_indicators` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you rerun the categorization notebook.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists as defined in the categorization notebook."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_scenario_data_world_r1.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('sr15_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"sr15_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "cats_15_no_lo = specs.pop('cats_15_no_lo')\n",
+ "marker= specs.pop('marker')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Assign years of interest and downselect to scenarios of interest for this assessment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = [2010, 2030, 2050]\n",
+ "table_years = [2030, 2050]\n",
+ "compare_year = 2010"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cats.remove('Above 2C')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats + ['no-climate-assessment'], year=years)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Initialize a `pyam.Statistics` instance¶"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "filters = [\n",
+ " (('IAM pathways', 'no & lo os 1.5'), {'category': cats_15_no_lo}),\n",
+ " (('IAM pathways', 'hi os 1.5'), {'category': ['1.5C high overshoot']}),\n",
+ " (('IAM pathways', 'S1'), {'marker': ['S1']}),\n",
+ " (('IAM pathways', 'S2'), {'marker': ['S2']}),\n",
+ " (('IAM pathways', 'S5'), {'marker': ['S5']}),\n",
+ " (('IAM pathways', 'LED'), {'marker': ['LED']}),\n",
+ " (('sectoral studies', 'Löffler et al. (2017)'), {'model': ['GENeSYS-MOD 1.0']}),\n",
+ " (('sectoral studies', 'IEA ETP (2017)'), {'model': ['IEA Energy Technology Perspective Model 2017']}),\n",
+ " (('sectoral studies', 'IEA WEM (2017)'), {'model': ['IEA World Energy Model 2017']})\n",
+ "]\n",
+ "\n",
+ "stats = pyam.Statistics(df=df, filters=filters, rows=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Share of renewables in primary energy and electricity generation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def add_stats_share(var_list, header, total, total_name, df=df, years=table_years):\n",
+ "\n",
+ " _df = df.filter(variable=var_list)\n",
+ " for v in var_list:\n",
+ " _df.require_variable(v, exclude_on_fail=True)\n",
+ " _df.filter(exclude=False, inplace=True)\n",
+ "\n",
+ " component = (\n",
+ " _df.timeseries()\n",
+ " .groupby(['model', 'scenario']).sum()\n",
+ " )\n",
+ " share = component / total * 100\n",
+ " \n",
+ " for y in years:\n",
+ " stats.add(share[y], header='Share of {}'.format(header),\n",
+ " subheader='in {} (%)'.format(total_name), row=y)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pe = df.filter(variable='Primary Energy').timeseries()\n",
+ "pe.index = pe.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pe_re_vars = [\n",
+ " 'Primary Energy|Biomass',\n",
+ " 'Primary Energy|Non-Biomass Renewables'\n",
+ "]\n",
+ "\n",
+ "add_stats_share(pe_re_vars, 'renewables', pe, 'primary energy')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ele = df.filter(variable='Secondary Energy|Electricity').timeseries()\n",
+ "ele.index = ele.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ele_re_vars = [\n",
+ " 'Secondary Energy|Electricity|Biomass',\n",
+ " 'Secondary Energy|Electricity|Non-Biomass Renewables'\n",
+ "]\n",
+ "\n",
+ "add_stats_share(ele_re_vars, 'renewables', ele, 'electricity generation')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Energy demand in buildings (relative to 2010)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bld = df.filter(variable='Final Energy|Residential and Commercial', year=years).timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for y in table_years:\n",
+ " stats.add(-(bld[y] / bld[compare_year] - 1) * 100,\n",
+ " header='Change in energy demand in buildings',\n",
+ " subheader='relative to {} (%)'.format(compare_year), row=y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Share of low-carbon fuels and electricity in the transport sector\n",
+ "\n",
+ "For the scenario presented by \"Löffler et al. (2017)\", the share of low-carbon fuels was read directly from one of the figures in the manuscript."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "trp = df.filter(variable='Final Energy|Transportation').timeseries()\n",
+ "trp.index = trp.index.droplevel([2, 3, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "trp_low_vars = [\n",
+ " 'Final Energy|Transportation|Electricity',\n",
+ " 'Final Energy|Transportation|Hydrogen',\n",
+ " 'Final Energy|Transportation|Liquids|Biomass'\n",
+ "]\n",
+ "add_stats_share(trp_low_vars, 'low-carbon fuels', trp, 'transport')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "trp_ele_vars = ['Final Energy|Transportation|Electricity']\n",
+ "add_stats_share(trp_ele_vars, 'electricity', trp, 'transport')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Industrial emissions (relative to 2010)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2_ind = df.filter(variable='Emissions|CO2|Energy|Demand|Industry', year=years).timeseries()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for y in table_years:\n",
+ " stats.add(-(co2_ind[y] / co2_ind[compare_year] - 1) * 100,\n",
+ " header='Industrial emissions reductions',\n",
+ " subheader='(based on current level) (%)', row=y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Display summary statistics table and export as `xlsx`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "summary = stats.summarize(center='median', interquartile=True, custom_format='{:.0f}')\n",
+ "summary = (\n",
+ " summary\n",
+ " .swaplevel(0, 2, axis=0).swaplevel(1, 2, axis=0)\n",
+ " .sort_index(axis=0, level=0, sort_remaining=False)\n",
+ ")\n",
+ "summary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "summary.to_excel('output/sr15_table_4.2_sectoral_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [default]",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/assessment/style_sr15.mplstyle b/assessment/style_sr15.mplstyle
new file mode 100644
index 0000000..3d534e1
--- /dev/null
+++ b/assessment/style_sr15.mplstyle
@@ -0,0 +1,6 @@
+font.family: arial
+font.size: 11
+axes.facecolor: white
+axes.edgecolor: black
+axes.linewidth: 0.75
+ytick.left: True
\ No newline at end of file
diff --git a/assessment/utils.py b/assessment/utils.py
new file mode 100644
index 0000000..11eb2fd
--- /dev/null
+++ b/assessment/utils.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+Auxiliary plotting functions for the notebooks
+of the IPCC SR15 scenario assessment
+
+@author: huppmann
+"""
+import numpy as np
+import matplotlib.pyplot as plt
+import pyam
+rc = pyam.run_control()
+
+
+def boxplot_by_cat(df, categories, column, years, mincount=7,
+ ymax=None, ymin=None, title=None, ylabel=None, xlabel=None,
+ legend=True, log_scale=False, hlines=None,
+ add_marker=None, ar5_format=False, save=False):
+
+ groupby = df.groupby(column)
+ _cats = len(categories) - 1
+ w = 0.6 / _cats
+
+ if add_marker is not None:
+ def marker_args(m):
+ return dict(zorder=3,
+ edgecolors=rc['edgecolors']['marker'][m],
+ c=rc['c']['marker'][m],
+ marker=rc['marker']['marker'][m],
+ linewidths=1)
+
+ for i, name in enumerate(categories):
+ if name not in groupby.groups or groupby.get_group(name).empty:
+ continue
+
+ _df = groupby.get_group(name)
+ c = rc['color'][column][name]
+
+ for j, y in enumerate(years):
+ lst = _df[y][~np.isnan(_df[y])]
+ pos = (0.75 / _cats * (i - _cats / 2) + j)
+
+ outliers = len(lst[lst > ymax])
+ if outliers > 0:
+ plt.text(pos - 0.01 * len(years),
+ ymax * (1.15 if log_scale else 1.02), outliers)
+
+ if len(lst) >= mincount:
+ p = plt.boxplot(lst, positions=[pos], widths=w * .90,
+ whis=0 if ar5_format else 'range', sym='',
+ patch_artist=True)
+ plt.tick_params(
+ axis='x', # changes apply to the x-axis
+ which='both', # both major and minor ticks are
+ bottom=False, # ticks along the bottom edge are off
+ top=False, # ticks along the top edge are off
+ labelbottom=True if len(years) > 1 else False)
+ plt.setp(p['boxes'], color=c)
+ plt.setp(p['medians'], color='black')
+
+ if ar5_format:
+ lst = _df[y][~np.isnan(_df[y])]
+ h = max(lst) - min(lst)
+ b = min(lst)
+ plt.bar(x=pos, height=h, bottom=b, zorder=2, width=w,
+ color='white', edgecolor='grey', linewidth=0.5,
+ label=None)
+ plt.scatter(x=[pos] * len(lst), y=lst, zorder=3,
+ c='grey', edgecolors='grey', linewidth=0.5,
+ marker='x', s=15, label=None)
+ else:
+ plt.scatter(x=[pos] * len(lst), y=lst, zorder=6,
+ c=c, edgecolors='black', marker='o',
+ s=30, label=None)
+ plt.plot([pos, pos], [max(lst), min(lst)], zorder=4,
+ color='black', linewidth=1, linestyle='-',
+ marker='_', markersize=8, markeredgewidth=1,
+ markeredgecolor='black')
+
+ if add_marker is not None:
+ for m in [i for i in _df.marker if isinstance(i, str)]:
+ _df_m = _df[_df.marker == m]
+ val = _df_m[y]
+ plt.scatter(x=pos, y=val, **marker_args(m),
+ s=50, label=None)
+
+ plt.plot([], c=c, label='{} [{}]'.format(name, len(_df)))
+
+ if add_marker is not None:
+ for m in add_marker:
+ plt.scatter(x=[], y=[], **marker_args(m), s=60, label=m)
+ if ar5_format:
+ plt.scatter(x=[], y=[], c='grey', edgecolors='grey', linewidth=0.5,
+ marker='x', s=15, label='other scenarios')
+
+ if hlines is not None:
+ plt.hlines(hlines, xmin=-1, xmax=len(years), colors=[(0.8, 0.8, 0.8)],
+ linewidths=0.8)
+
+ if legend:
+ plt.legend()
+ if title is not None:
+ plt.title(title)
+ if xlabel is not None:
+ plt.xlabel(xlabel)
+ if ylabel is not None:
+ plt.ylabel(ylabel)
+ if log_scale:
+ plt.yscale('log')
+ plt.xlim(-0.6, (len(years) - 0.4))
+ if ymax or ymin:
+ plt.ylim(ymax=ymax, ymin=ymin)
+ plt.xticks(range(0, len(years)), years)
+
+ if save:
+ plt.savefig(save)
diff --git a/bibliography/README.md b/bibliography/README.md
new file mode 100644
index 0000000..741d6c3
--- /dev/null
+++ b/bibliography/README.md
@@ -0,0 +1,9 @@
+# Bibliography
+
+This folder contains the bibliographic information of the scenario references
+and the recommended citation of the scenario ensemble and the notebooks
+as `ris`, `enl` and `bib` format.
+
+The table `scenario_references.csv` contains the bibliographic details
+for all scenarios included in the ensemble and is used by the notebook
+`sr15_2.0_categories_indicators` when defining the metadata indicators.
diff --git a/bibliography/iamc_1.5c_scenario_data.bib b/bibliography/iamc_1.5c_scenario_data.bib
new file mode 100644
index 0000000..a400347
--- /dev/null
+++ b/bibliography/iamc_1.5c_scenario_data.bib
@@ -0,0 +1,287 @@
+@article{Bauer:2018,
+ author = {Bauer, Nico and Rose, Steven K. and Fujimori, Shinichiro and Van Vuuren, Detlef and Weyant, John and Wise, Marshall and Cui, Yiyun and Daioglou, Vassilis and Gidden, Matthew J. and Kato, Etsushi and Kitous, Alban and Leblanc, Florian and Sands, Ronald D. and Sano, Fuminori and Strefler, Jessica and Tsutsui, Junichi and Bibas, Ruben and Fricko, Oliver and Hasegawa, Tomoko and Klein, David and Kurosawa, Atsushi and Mima, Silvana and Muratori, Matteo},
+ title = {{Global energy sector emission reductions and bioenergy use: overview of the bioenergy demand phase of the EMF-33 model comparison}},
+ journal = {Climatic Change},
+ doi= {10.1007/s10584-018-2226-y},
+ year = {forthcoming}
+}
+
+@article{Bertram:2018,
+ author = {Bertram, Christoph and Luderer, Gunnar and Popp, Alexander and Minx, Jan Christoph and Lamb, William, F. and Stevanović, Miodrag and Humpenöder, Florian and Giannousakis, Anastasis and Kriegler, Elmar},
+ title = {{Targeted policies can compensate most of the increased sustainability risks in 1.5 °C mitigation scenarios}},
+ journal = {Environmental Research Letters},
+ volume = {13},
+ number = {6},
+ pages = {064038},
+ abstract = {Meeting the 1.5 °C goal will require a rapid scale-up of zero-carbon energy supply, fuel switching to electricity, efficiency and demand-reduction in all sectors, and the replenishment of natural carbon sinks. These transformations will have immediate impacts on various of the sustainable development goals. As goals such as affordable and clean energy and zero hunger are more immediate to great parts of global population, these impacts are central for societal acceptability of climate policies. Yet, little is known about how the achievement of other social and environmental sustainability objectives can be directly managed through emission reduction policies. In addition, the integrated assessment literature has so far emphasized a single, global (cost-minimizing) carbon price as the optimal mechanism to achieve emissions reductions. In this paper we introduce a broader suite of policies—including direct sector-level regulation, early mitigation action, and lifestyle changes—into the integrated energy-economy-land-use modeling system REMIND-MAgPIE. We examine their impact on non-climate sustainability issues when mean warming is to be kept well below 2 °C or 1.5 °C. We find that a combination of these policies can alleviate air pollution, water extraction, uranium extraction, food and energy price hikes, and dependence on negative emissions technologies, thus resulting in substantially reduced sustainability risks associated with mitigating climate change. Importantly, we find that these targeted policies can more than compensate for most sustainability risks of increasing climate ambition from 2 °C to 1.5 °C.},
+ doi= {10.1088/1748-9326/aac3ec},
+ year = {2018}
+}
+
+@article{Grubler:2018,
+ author = {Grubler, Arnulf and Wilson, Charlie and Bento, Nuno and Boza-Kiss, Benigna and Krey, Volker and McCollum, David L. and Rao, Narasimha D. and Riahi, Keywan and Rogelj, Joeri and De Stercke, Simon and Cullen, Jonathan and Frank, Stefan and Fricko, Oliver and Guo, Fei and Gidden, Matt and Havlík, Petr and Huppmann, Daniel and Kiesewetter, Gregor and Rafaj, Peter and Schoepp, Wolfgang and Valin, Hugo},
+ title = {{A low energy demand scenario for meeting the 1.5 °C target and sustainable development goals without negative emission technologies}},
+ journal = {Nature Energy},
+ volume = {3},
+ number = {6},
+ pages = {515-527},
+ abstract = {Scenarios that limit global warming to 1.5 °C describe major transformations in energy supply and ever-rising energy demand. Here, we provide a contrasting perspective by developing a narrative of future change based on observable trends that results in low energy demand. We describe and quantify changes in activity levels and energy intensity in the global North and global South for all major energy services. We project that global final energy demand by 2050 reduces to 245 EJ, around 40% lower than today, despite rises in population, income and activity. Using an integrated assessment modelling framework, we show how changes in the quantity and type of energy services drive structural change in intermediate and upstream supply sectors (energy and land use). Down-sizing the global energy system dramatically improves the feasibility of a low-carbon supply-side transformation. Our scenario meets the 1.5 °C climate target as well as many sustainable development goals, without relying on negative emission technologies.},
+ doi= {10.1038/s41560-018-0172-6},
+ year = {2018}
+}
+
+@article{Holz:2018,
+ author = {Holz, Christian and Siegel, Lori S. and Johnston, Eleanor and Jones, Andrew P. and Sterman, Jones},
+ title = {{Ratcheting ambition to limit warming to 1.5 °C–trade-offs between emission reductions and carbon dioxide removal}},
+ journal = {Environmental Research Letters},
+ volume = {13},
+ number = {6},
+ pages = {064028},
+ abstract = {Mitigation scenarios to limit global warming to 1.5 °C or less in 2100 often rely on large amounts of carbon dioxide removal (CDR), which carry significant potential social, environmental, political and economic risks. A precautionary approach to scenario creation is therefore indicated. This letter presents the results of such a precautionary modelling exercise in which the models C-ROADS and En-ROADS were used to generate a series of 1.5 °C mitigation scenarios that apply increasingly stringent constraints on the scale and type of CDR available. This allows us to explore the trade-offs between near-term stringency of emission reductions and assumptions about future availability of CDR. In particular, we find that regardless of CDR assumptions, near-term ambition increase (‘ratcheting’) is required for any 1.5 °C pathway, making this letter timely for the facilitative, or Talanoa, dialogue to be conducted by the UNFCCC in 2018. By highlighting the difference between net and gross reduction rates, often obscured in scenarios, we find that mid-term gross CO 2 emission reduction rates in scenarios with CDR constraints increase to levels without historical precedence. This in turn highlights, in addition to the need to substantially increase CO 2 reduction rates, the need to improve emission reductions for non-CO 2 greenhouse gases. Further, scenarios in which all or part of the CDR is implemented as non-permanent storage exhibit storage loss emissions, which partly offset CDR, highlighting the importance of differentiating between net and gross CDR in scenarios. We find in some scenarios storage loss trending to similar values as gross CDR, indicating that gross CDR would have to be maintained simply to offset the storage losses of CO 2 sequestered earlier, without any additional net climate benefit.},
+ doi= {10.1088/1748-9326/aac0c1},
+ year = {2018}
+}
+
+@misc{Huppmann:2018:scenario-data,
+ author = {Huppmann, Daniel and Kriegler, Elmar and Krey, Volker and Riahi, Keywan and Rogelj, Joeri and Rose, Steven K. and Weyant, John and Bauer, Nico and Bertram, Christoph and Bosetti, Valentina and Calvin, Katherine and Doelman, Jonathan and Drouet, Laurent and Emmerling, Johannes and Frank, Stefan and Fujimori, Shinichiro and Gernaat, David and Grubler, Arnulf and Guivarch, Celine and Haigh, Martin and Holz, Christian and Iyer, Gokul and Kato, Etsushi and Keramidas, Kimon and Kitous, Alban and Leblanc, Florian and Liu, Jing-Yu and Löffler, Konstantin and Luderer, Gunnar and Marcucci, Adriana and McCollum, David and Mima, Silvana and Popp, Alexander and Sands, Ronald D. and Sano, Fuminori and Strefler, Jessica and Tsutsui, Junichi and Van Vuuren, Detlef and Vrontisi, Zoi and Wise, Marshall and Zhang, Runsen},
+ title = {{IAMC 1.5°C Scenario Explorer and Data hosted by IIASA}},
+ publisher = {Integrated Assessment Modeling Consortium & International Institute for Applied Systems Analysis},
+ howpublished = {Integrated Assessment Modeling Consortium & International Institute for Applied Systems Analysis},
+ doi= {10.22022/SR15/08-2018.15429 },
+ year = {2018}
+}
+
+@article{Huppmann:2018:NCC,
+ author = {Huppmann, Daniel and Rogelj, Joeri and Krey, Volker and Kriegler, Elmar and Riahi, Keywan},
+ title = {{A new scenario resource for integrated 1.5 °C research}},
+ journal = {Nature Climate Change},
+ doi= {10.1038/s41558-018-0317-4},
+ year = {2018}
+}
+
+@misc{Huppmann:2018:assessment-notebooks,
+ author = {Huppmann, Daniel and Rogelj, Joeri and Kriegler, Elmar and Mundaca, Luis and Forster, Piers and Kobayashi, Shigeki and Séferian, Roland and Vilariño, María Virginia},
+ title = {{Scenario analysis notebooks for the IPCC Special Report on Global Warming of 1.5°C}},
+ doi= {10.22022/SR15/08-2018.15428},
+ year = {2018}
+}
+
+@book{IEA:2017:ETP,
+ author = {International Energy Agency,},
+ title = {{Energy Technology Perspectives 2017}},
+ doi= {10.1787/energy_tech-2017-en},
+ year = {2017}
+}
+
+@book{IEA:2017:WEO,
+ author = {International Energy Agency,},
+ title = {{World Energy Outlook 2017}},
+ doi= {10.1787/weo-2017-en},
+ year = {2017}
+}
+
+@article{Kriegler:2018,
+ author = {Kriegler, Elmar and Bertram, Christoph and Kuramochi, Takeshi and Jakob, Michael and Pehl, Michaja and Stevanovic, Miodrag and Höhne, Niklas and Luderer, Gunnar and Minx, Jan C. and Fekete, Hanna and Hilaire, Jérôme and Luna, Lisa and Popp, Alexander and Steckel, Jan Christoph and Sterl, Sebastian and Yalew, Amsalu and Dietrich, Jan-Philipp and Edenhofer, Ottmar},
+ title = {{Short term policies to keep the door open for Paris climate goals}},
+ journal = {Environmental Research Letters},
+ volume = {13},
+ number = {7},
+ pages = {074022},
+ doi= {10.1088/1748-9326/aac4f1},
+ year = {2018}
+}
+
+@article{Liu:2018,
+ author = {Liu, Jing-Yu and Fujimori, Shinichiro and Takahashi, Kiyoshi and Hasegawa, Tomoko and Su, Xuanming and Masui, Toshihiko},
+ title = {{Socioeconomic factors and future challenges of the goal of limiting the increase in global average temperature to 1.5°C}},
+ journal = {Carbon Management},
+ pages = {1-11},
+ doi= {10.1080/17583004.2018.1477374},
+ year = {2018}
+}
+
+@article{Loffler:2017,
+ author = {Löffler, Konstantin and Hainsch, Karlo and Burandt, Thorsten and Oei, Pao-Yu and Kemfert, Claudia and von Hirschhausen, Christian},
+ title = {{Designing a Model for the Global Energy System -- GENeSYS-MOD: An Application of the Open-Source Energy Modeling System (OSeMOSYS)}},
+ journal = {Energies},
+ volume = {10},
+ number = {10},
+ pages = {1468},
+ abstract = {This paper develops a path for the global energy system up to 2050, presenting a new application of the open-source energy modeling system (OSeMOSYS) to the community. It allows quite disaggregate energy and emission analysis: Global Energy System Model (GENeSYS-MOD) uses a system of linear equations of the energy system to search for lowest-cost solutions for a secure energy supply, given externally defined constraints, mainly in terms of CO2-emissions. The general algebraic modeling system (GAMS) version of OSeMOSYS is updated to the newest version and, in addition, extended and enhanced to include e.g., a modal split for transport, an improved trading system, and changes to storages. The model can be scaled from small-scale applications, e.g., a company, to cover the global energy system. The paper also includes an application of GENeSYS-MOD to analyze decarbonization scenarios at the global level, broken down into 10 regions. Its main focus is on interdependencies between traditionally segregated sectors: electricity, transportation, and heating; which are all included in the model. Model calculations suggests that in order to achieve the 1.5–2 °C target, a combination of renewable energy sources provides the lowest-cost solution, solar photovoltaic being the dominant source. Average costs of electricity generation in 2050 are about 4 €cents/kWh (excluding infrastructure and transportation costs).},
+ doi= {10.3390/en10101468},
+ year = {2017}
+}
+
+@article{Luderer:2013,
+ author = {Luderer, Gunnar and Pietzcker, Robert C. and Bertram, Christoph and Kriegler, Elmar and Meinshausen, Malte and Edenhofer, Ottmar},
+ title = {{Economic mitigation challenges: how further delay closes the door for achieving climate targets}},
+ journal = {Environmental Research Letters},
+ volume = {8},
+ number = {3},
+ pages = {034033},
+ abstract = {While the international community aims to limit global warming to below 2 ° C to prevent dangerous climate change, little progress has been made towards a global climate agreement to implement the emissions reductions required to reach this target. We use an integrated energy–economy–climate modeling system to examine how a further delay of cooperative action and technology availability affect climate mitigation challenges. With comprehensive emissions reductions starting after 2015 and full technology availability we estimate that maximum 21st century warming may still be limited below 2 ° C with a likely probability and at moderate economic impacts. Achievable temperature targets rise by up to ∼0.4 ° C if the implementation of comprehensive climate policies is delayed by another 15 years, chiefly because of transitional economic impacts. If carbon capture and storage (CCS) is unavailable, the lower limit of achievable targets rises by up to ∼0.3 ° C. Our results show that progress in international climate negotiations within this decade is imperative to keep the 2 ° C target within reach.},
+ doi= {10.1088/1748-9326/8/3/034033},
+ year = {2013}
+}
+
+@article{Luderer:2018,
+ author = {Luderer, Gunnar and Vrontisi, Zoi and Bertram, Christoph and Edelenbosch, Oreane Y. and Pietzcker, Robert C. and Rogelj, Joeri and De Boer, Harmen Sytze and Drouet, Laurent and Emmerling, Johannes and Fricko, Oliver and Fujimori, Shinichiro and Havlík, Petr and Iyer, Gokul and Keramidas, Kimon and Kitous, Alban and Pehl, Michaja and Krey, Volker and Riahi, Keywan and Saveyn, Bert and Tavoni, Massimo and Van Vuuren, Detlef P. and Kriegler, Elmar},
+ title = {{Residual fossil CO2 emissions in 1.5–2 °C pathways}},
+ journal = {Nature Climate Change},
+ volume = {8},
+ number = {7},
+ pages = {626-633},
+ abstract = {The Paris Agreement—which is aimed at holding global warming well below 2 °C while pursuing efforts to limit it below 1.5 °C—has initiated a bottom-up process of iteratively updating nationally determined contributions to reach these long-term goals. Achieving these goals implies a tight limit on cumulative net CO2 emissions, of which residual CO2 emissions from fossil fuels are the greatest impediment. Here, using an ensemble of seven integrated assessment models (IAMs), we explore the determinants of these residual emissions, focusing on sector-level contributions. Even when strengthened pre-2030 mitigation action is combined with very stringent long-term policies, cumulative residual CO2 emissions from fossil fuels remain at 850–1,150 GtCO2 during 2016–2100, despite carbon prices of US$130–420 per tCO2 by 2030. Thus, 640–950 GtCO2 removal is required for a likely chance of limiting end-of-century warming to 1.5 °C. In the absence of strengthened pre-2030 pledges, long-term CO2 commitments are increased by 160–330 GtCO2, further jeopardizing achievement of the 1.5 °C goal and increasing dependence on CO2 removal.},
+ doi= {10.1038/s41558-018-0198-6},
+ year = {2018}
+}
+
+@article{Marcucci:2017,
+ author = {Marcucci, Adriana and Kypreos, Socrates and Panos, Evangelos},
+ title = {{The road to achieving the long-term Paris targets: energy transition and the role of direct air capture}},
+ journal = {Climatic Change},
+ volume = {144},
+ number = {2},
+ pages = {181-193},
+ abstract = {In this paper, we quantify the energy transition and economic consequences of the long-term targets from the Paris agreement, with a particular focus on the targets of limiting global warming by the end of the century to 2 and 1.5 °C. The study assumes early actions and quantifies the market penetration of low carbon technologies, the emission pathways and the economic costs for an efficient reduction of greenhouse gas (GHG) emissions such that the temperature limit is not exceeded. We evaluate the potential role of direct air capture (DAC) and its impact on policy costs and energy consumption. DAC is a technology that removes emissions directly from the atmosphere contributing to negative carbon emissions. We find that, with our modelling assumptions, limiting global temperature to 1.5 °C is only possible when using DAC. Our results show that the DAC technology can play an important role in realising deep decarbonisation goals and in the reduction of regional and global mitigation costs with stringent targets. DAC acts a substitute to Bio-Energy with Carbon Capture and Storage (BECCS) in the stringent scenarios. For this analysis, we use the model MERGE-ETL, a technology-rich integrated assessment model with endogenous learning.},
+ doi= {10.1007/s10584-017-2051-8},
+ year = {2017}
+}
+
+@article{McCollum:2018,
+ author = {McCollum, David L. and Zhou, Wenji and Bertram, Christoph and de Boer, Harmen-Sytze and Bosetti, Valentina and Busch, Sebastian and Després, Jacques and Drouet, Laurent and Emmerling, Johannes and Fay, Marianne and Fricko, Oliver and Fujimori, Shinichiro and Gidden, Matthew and Harmsen, Mathijs and Huppmann, Daniel and Iyer, Gokul and Krey, Volker and Kriegler, Elmar and Nicolas, Claire and Pachauri, Shonali and Parkinson, Simon and Poblete-Cazenave, Miguel and Rafaj, Peter and Rao, Narasimha and Rozenberg, Julie and Schmitz, Andreas and Schoepp, Wolfgang and van Vuuren, Detlef and Riahi, Keywan},
+ title = {{Energy investment needs for fulfilling the Paris Agreement and achieving the Sustainable Development Goals}},
+ journal = {Nature Energy},
+ volume = {3},
+ number = {7},
+ pages = {589-599},
+ abstract = {Low-carbon investments are necessary for driving the energy system transformation that is called for by both the Paris Agreement and Sustainable Development Goals. Improving understanding of the scale and nature of these investments under diverging technology and policy futures is therefore of great importance to decision makers. Here, using six global modelling frameworks, we show that the pronounced reallocation of the investment portfolio required to transform the energy system will not be initiated by the current suite of countries’ Nationally Determined Contributions. Charting a course toward ‘well below 2 °C’ instead sees low-carbon investments overtaking fossil investments globally by around 2025 or before and growing thereafter. Pursuing the 1.5 °C target demands a marked upscaling in low-carbon capital beyond that of a 2 °C-consistent future. Actions consistent with an energy transformation would increase the costs of achieving the goals of energy access and food security, but reduce the costs of achieving air-quality goals.},
+ doi= {10.1038/s41560-018-0179-z},
+ year = {2018}
+}
+
+@article{Riahi:2017,
+ author = {Riahi, Keywan and van Vuuren, Detlef P. and Kriegler, Elmar and Edmonds, Jae and O’Neill, Brian C. and Fujimori, Shinichiro and Bauer, Nico and Calvin, Katherine and Dellink, Rob and Fricko, Oliver and Lutz, Wolfgang and Popp, Alexander and Cuaresma, Jesus Crespo and Kc, Samir and Leimbach, Marian and Jiang, Leiwen and Kram, Tom and Rao, Shilpa and Emmerling, Johannes and Ebi, Kristie and Hasegawa, Tomoko and Havlik, Petr and Humpenöder, Florian and Da Silva, Lara Aleluia and Smith, Steve and Stehfest, Elke and Bosetti, Valentina and Eom, Jiyong and Gernaat, David and Masui, Toshihiko and Rogelj, Joeri and Strefler, Jessica and Drouet, Laurent and Krey, Volker and Luderer, Gunnar and Harmsen, Mathijs and Takahashi, Kiyoshi and Baumstark, Lavinia and Doelman, Jonathan C. and Kainuma, Mikiko and Klimont, Zbigniew and Marangoni, Giacomo and Lotze-Campen, Hermann and Obersteiner, Michael and Tabeau, Andrzej and Tavoni, Massimo},
+ title = {{The Shared Socioeconomic Pathways and their energy, land use, and greenhouse gas emissions implications: An overview}},
+ journal = {Global Environmental Change},
+ volume = {42},
+ pages = {153-168},
+ abstract = {This paper presents the overview of the Shared Socioeconomic Pathways (SSPs) and their energy, land use, and emissions implications. The SSPs are part of a new scenario framework, established by the climate change research community in order to facilitate the integrated analysis of future climate impacts, vulnerabilities, adaptation, and mitigation. The pathways were developed over the last years as a joint community effort and describe plausible major global developments that together would lead in the future to different challenges for mitigation and adaptation to climate change. The SSPs are based on five narratives describing alternative socio-economic developments, including sustainable development, regional rivalry, inequality, fossil-fueled development, and middle-of-the-road development. The long-term demographic and economic projections of the SSPs depict a wide uncertainty range consistent with the scenario literature. A multi-model approach was used for the elaboration of the energy, land-use and the emissions trajectories of SSP-based scenarios. The baseline scenarios lead to global energy consumption of 400–1200 EJ in 2100, and feature vastly different land-use dynamics, ranging from a possible reduction in cropland area up to a massive expansion by more than 700 million hectares by 2100. The associated annual CO2 emissions of the baseline scenarios range from about 25 GtCO2 to more than 120 GtCO2 per year by 2100. With respect to mitigation, we find that associated costs strongly depend on three factors: (1) the policy assumptions, (2) the socio-economic narrative, and (3) the stringency of the target. The carbon price for reaching the target of 2.6 W/m2 that is consistent with a temperature change limit of 2 °C, differs in our analysis thus by about a factor of three across the SSP marker scenarios. Moreover, many models could not reach this target from the SSPs with high mitigation challenges. While the SSPs were designed to represent different mitigation and adaptation challenges, the resulting narratives and quantifications span a wide range of different futures broadly representative of the current literature. This allows their subsequent use and development in new assessments and research projects. Critical next steps for the community scenario process will, among others, involve regional and sectoral extensions, further elaboration of the adaptation and impacts dimension, as well as employing the SSP scenarios with the new generation of earth system models as part of the 6th climate model intercomparison project (CMIP6).},
+ doi= {10.1016/j.gloenvcha.2016.05.009},
+ keywords = {Shared Socioeconomic Pathways
+SSP
+Climate change
+RCP
+Community scenarios
+Mitigation
+Adaptation},
+ year = {2017}
+}
+
+@article{Rogelj:2015,
+ author = {Rogelj, Joeri and Luderer, Gunnar and Pietzcker, Robert C. and Kriegler, Elmar and Schaeffer, Michiel and Krey, Volker and Riahi, Keywan},
+ title = {{Energy system transformations for limiting end-of-century warming to below 1.5 °C}},
+ journal = {Nature Climate Change},
+ volume = {5},
+ number = {6},
+ pages = {519-527},
+ doi= {10.1038/nclimate2572},
+ year = {2015}
+}
+
+@article{Rogelj:2013:NCC,
+ author = {Rogelj, Joeri and McCollum, David L. and O’Neill, Brian C. and Riahi, Keywan},
+ title = {{2020 emissions levels required to limit warming to below 2°C}},
+ journal = {Nature Climate Change},
+ volume = {3},
+ pages = {405-412},
+ doi= {10.1038/nclimate1758},
+ year = {2013}
+}
+
+@article{Rogelj:2013:Nature,
+ author = {Rogelj, Joeri and McCollum, David L. and Reisinger, Andy and Meinshausen, Malte and Riahi, Keywan},
+ title = {{Probabilistic cost estimates for climate change mitigation}},
+ journal = {Nature},
+ volume = {493},
+ pages = {79-83},
+ doi= {10.1038/nature11787},
+ year = {2013}
+}
+
+@article{Rogelj:2018,
+ author = {Rogelj, Joeri and Popp, Alexander and Calvin, Katherine V. and Luderer, Gunnar and Emmerling, Johannes and Gernaat, David and Fujimori, Shinichiro and Strefler, Jessica and Hasegawa, Tomoko and Marangoni, Giacomo and Krey, Volker and Kriegler, Elmar and Riahi, Keywan and van Vuuren, Detlef P. and Doelman, Jonathan and Drouet, Laurent and Edmonds, Jae and Fricko, Oliver and Harmsen, Mathijs and Havlík, Petr and Humpenöder, Florian and Stehfest, Elke and Tavoni, Massimo},
+ title = {{Scenarios towards limiting global mean temperature increase below 1.5 °C}},
+ journal = {Nature Climate Change},
+ volume = {8},
+ pages = {325-332},
+ abstract = {The 2015 Paris Agreement calls for countries to pursue efforts to limit global-mean temperature rise to 1.5 °C. The transition pathways that can meet such a target have not, however, been extensively explored. Here we describe scenarios that limit end-of-century radiative forcing to 1.9 W m−2, and consequently restrict median warming in the year 2100 to below 1.5 °C. We use six integrated assessment models and a simple climate model, under different socio-economic, technological and resource assumptions from five Shared Socio-economic Pathways (SSPs). Some, but not all, SSPs are amenable to pathways to 1.5 °C. Successful 1.9 W m−2 scenarios are characterized by a rapid shift away from traditional fossil-fuel use towards large-scale low-carbon energy supplies, reduced energy use, and carbon-dioxide removal. However, 1.9 W m−2 scenarios could not be achieved in several models under SSPs with strong inequalities, high baseline fossil-fuel use, or scattered short-term climate policy. Further research can help policy-makers to understand the real-world implications of these scenarios.},
+ doi= {10.1038/s41558-018-0091-3},
+ year = {2018}
+}
+
+@incollection{SR15:Ch2:2018,
+ author = {Rogelj, Joeri and Shindell, Drew and Jiang, Kejun and Fifita, Solomone and Forster, Piers and Ginzburg, Veronika and Handa, Collins and Kheshgi, Haroon and Kobayashi, Shigeki and Kriegler, Elmar and Mundaca, Luis and Séférian, Roland and Vilariño, Mario V.},
+ title = {{Mitigation pathways compatible with 1.5°C in the context of sustainable development}},
+ booktitle = {Special Report on the impacts of global warming of 1.5 °C},
+ publisher = {Intergovernmental Panel on Climate Change},
+ address = {Geneva},
+ url = {http://www.ipcc.ch/report/sr15/},
+ year = {2018}
+}
+
+@book{Shell:2018,
+ author = {Shell},
+ title = {{Meeting the goals of the Paris Agreement}},
+ publisher = {Shell International B.V.},
+ year = {2018}
+}
+
+@article{Strefler:2018,
+ author = {Strefler, Jessica and Bauer, Nico and Kriegler, Elmar and Popp, Alexander and Giannousakis, Anastasis and Edenhofer, Ottmar},
+ title = {{Between Scylla and Charybdis: Delayed mitigation narrows the passage between large-scale CDR and high costs}},
+ journal = {Environmental Research Letters},
+ volume = {13},
+ number = {4},
+ pages = {044015},
+ abstract = {There are major concerns about the sustainability of large-scale deployment of carbon dioxide removal (CDR) technologies. It is therefore an urgent question to what extent CDR will be needed to implement the long term ambition of the Paris Agreement. Here we show that ambitious near term mitigation significantly decreases CDR requirements to keep the Paris climate targets within reach. Following the nationally determined contributions (NDCs) until 2030 makes 2 °C unachievable without CDR. Reducing 2030 emissions by 20% below NDC levels alleviates the trade-off between high transitional challenges and high CDR deployment. Nevertheless, transitional challenges increase significantly if CDR is constrained to less than 5 Gt CO 2 a −1 in any year. At least 8 Gt CO 2 a −1 CDR are necessary in the long term to achieve 1.5 °C and more than 15 Gt CO 2 a −1 to keep transitional challenges in bounds.},
+ doi= {10.1088/1748-9326/aab2ba},
+ year = {2018}
+}
+
+@article{vanVuuren:2018,
+ author = {van Vuuren, Detlef P. and Stehfest, Elke and Gernaat, David E. H. J. and van den Berg, Maarten and Bijl, David L. and de Boer, Harmen Sytze and Daioglou, Vassilis and Doelman, Jonathan C. and Edelenbosch, Oreane Y. and Harmsen, Mathijs and Hof, Andries F. and van Sluisveld, Mariësse A. E.},
+ title = {{Alternative pathways to the 1.5 °C target reduce the need for negative emission technologies}},
+ journal = {Nature Climate Change},
+ volume = {8},
+ number = {5},
+ pages = {391-397},
+ abstract = {Mitigation scenarios that achieve the ambitious targets included in the Paris Agreement typically rely on greenhouse gas emission reductions combined with net carbon dioxide removal (CDR) from the atmosphere, mostly accomplished through large-scale application of bioenergy with carbon capture and storage, and afforestation. However, CDR strategies face several difficulties such as reliance on underground CO2 storage and competition for land with food production and biodiversity protection. The question arises whether alternative deep mitigation pathways exist. Here, using an integrated assessment model, we explore the impact of alternative pathways that include lifestyle change, additional reduction of non-CO2 greenhouse gases and more rapid electrification of energy demand based on renewable energy. Although these alternatives also face specific difficulties, they are found to significantly reduce the need for CDR, but not fully eliminate it. The alternatives offer a means to diversify transition pathways to meet the Paris Agreement targets, while simultaneously benefiting other sustainability goals.},
+ doi= {10.1038/s41558-018-0119-8},
+ year = {2018}
+}
+
+@article{Vrontisi:2018,
+ author = {Vrontisi, Zoi and Luderer, Gunnar and Saveyn, Bert and Keramidas, Kimon and Reis, Lara Aleluia and Baumstark, Lavinia and Bertram, Christoph and Sytze de, Harmen Boer and Drouet, Laurent and Fragkiadakis, Kostas and Fricko, Oliver and Fujimori, Shinichiro and Guivarch, Celine and Kitous, Alban and Krey, Volker and Kriegler, Elmar and Ó Broin, Eoin and Paroussos, Leonidas and van Vuuren, Detlef},
+ title = {{Enhancing global climate policy ambition towards a 1.5 °C stabilization: a short-term multi-model assessment}},
+ journal = {Environmental Research Letters},
+ volume = {13},
+ number = {4},
+ pages = {044039},
+ abstract = {The Paris Agreement is a milestone in international climate policy as it establishes a global mitigation framework towards 2030 and sets the ground for a potential 1.5 °C climate stabilization. To provide useful insights for the 2018 UNFCCC Talanoa facilitative dialogue, we use eight state-of-the-art climate-energy-economy models to assess the effectiveness of the Intended Nationally Determined Contributions (INDCs) in meeting high probability 1.5 and 2 °C stabilization goals. We estimate that the implementation of conditional INDCs in 2030 leaves an emissions gap from least cost 2 °C and 1.5 °C pathways for year 2030 equal to 15.6 (9.0–20.3) and 24.6 (18.5–29.0) GtCO 2 eq respectively. The immediate transition to a more efficient and low-carbon energy system is key to achieving the Paris goals. The decarbonization of the power supply sector delivers half of total},
+ doi= {10.1088/1748-9326/aab53e},
+ year = {2018}
+}
+
+@article{Zhang:2018,
+ author = {Zhang, Runsen and Fujimori, Shinichiro and Hanaoka, Tatsuya},
+ title = {{The contribution of transport policies to the mitigation potential and cost of 2 °C and 1.5 °C goals}},
+ journal = {Environmental Research Letters},
+ volume = {13},
+ number = {5},
+ pages = {054008},
+ abstract = {The transport sector contributes around a quarter of global CO 2 emissions; thus, low-carbon transport policies are required to achieve the 2 °C and 1.5 °C targets. In this paper, representative transport policy scenarios are structured with the aim of achieving a better understanding of the interaction between the transport sector and the macroeconomy. To accomplish this, the Asia–Pacific Integrated Model/Transport (AIM/Transport) model, coupled with a computable general equilibrium model (AIM/CGE), is used to simulate the potential for different transport policy interventions to reduce emissions and cost over the period 2005–2100. The results show that deep decarbonization in the transport sector can be achieved by implementing transport policies such as energy efficiency improvements, vehicle technology innovations particularly the deployment of electric vehicles, public transport developments, and increasing the car occupancy rate. Technological transformations such as vehicle technological innovations and energy efficiency improvements provide the most significant reduction potential. The key finding is that low-carbon transport policies can reduce the carbon price, gross domestic product loss rate, and welfare loss rate generated by climate mitigation policies to limit global warming to 2 °C and 1.5 °C. Interestingly, the contribution of transport policies is more effective for stringent climate change targets in the 1.5 °C scenario, which implies that the stronger the mitigation intensity, the more transport specific policy is required. The transport sector requires attention to achieve the goal of stringent climate change mitigation.},
+ doi= {10.1088/1748-9326/aabb0d},
+ year = {2018}
+}
+
diff --git a/bibliography/iamc_1.5c_scenario_data.enl b/bibliography/iamc_1.5c_scenario_data.enl
new file mode 100644
index 0000000..2206a44
Binary files /dev/null and b/bibliography/iamc_1.5c_scenario_data.enl differ
diff --git a/bibliography/iamc_1.5c_scenario_data.ris b/bibliography/iamc_1.5c_scenario_data.ris
new file mode 100644
index 0000000..3a13a26
--- /dev/null
+++ b/bibliography/iamc_1.5c_scenario_data.ris
@@ -0,0 +1,712 @@
+TY - JOUR
+AU - Bauer, Nico
+AU - Rose, Steven K.
+AU - Fujimori, Shinichiro
+AU - Van Vuuren, Detlef
+AU - Weyant, John
+AU - Wise, Marshall
+AU - Cui, Yiyun
+AU - Daioglou, Vassilis
+AU - Gidden, Matthew J.
+AU - Kato, Etsushi
+AU - Kitous, Alban
+AU - Leblanc, Florian
+AU - Sands, Ronald D.
+AU - Sano, Fuminori
+AU - Strefler, Jessica
+AU - Tsutsui, Junichi
+AU - Bibas, Ruben
+AU - Fricko, Oliver
+AU - Hasegawa, Tomoko
+AU - Klein, David
+AU - Kurosawa, Atsushi
+AU - Mima, Silvana
+AU - Muratori, Matteo
+DO - 10.1007/s10584-018-2226-y
+PY - forthcoming
+ST - Global energy sector emission reductions and bioenergy use: overview of the bioenergy demand phase of the EMF-33 model comparison
+T2 - Climatic Change
+TI - Global energy sector emission reductions and bioenergy use: overview of the bioenergy demand phase of the EMF-33 model comparison
+ID - 10
+ER -
+
+
+TY - JOUR
+AB - Meeting the 1.5 °C goal will require a rapid scale-up of zero-carbon energy supply, fuel switching to electricity, efficiency and demand-reduction in all sectors, and the replenishment of natural carbon sinks. These transformations will have immediate impacts on various of the sustainable development goals. As goals such as affordable and clean energy and zero hunger are more immediate to great parts of global population, these impacts are central for societal acceptability of climate policies. Yet, little is known about how the achievement of other social and environmental sustainability objectives can be directly managed through emission reduction policies. In addition, the integrated assessment literature has so far emphasized a single, global (cost-minimizing) carbon price as the optimal mechanism to achieve emissions reductions. In this paper we introduce a broader suite of policies—including direct sector-level regulation, early mitigation action, and lifestyle changes—into the integrated energy-economy-land-use modeling system REMIND-MAgPIE. We examine their impact on non-climate sustainability issues when mean warming is to be kept well below 2 °C or 1.5 °C. We find that a combination of these policies can alleviate air pollution, water extraction, uranium extraction, food and energy price hikes, and dependence on negative emissions technologies, thus resulting in substantially reduced sustainability risks associated with mitigating climate change. Importantly, we find that these targeted policies can more than compensate for most sustainability risks of increasing climate ambition from 2 °C to 1.5 °C.
+AU - Bertram, Christoph
+AU - Luderer, Gunnar
+AU - Popp, Alexander
+AU - Minx, Jan Christoph
+AU - Lamb, William, F.
+AU - Stevanović, Miodrag
+AU - Humpenöder, Florian
+AU - Giannousakis, Anastasis
+AU - Kriegler, Elmar
+DO - 10.1088/1748-9326/aac3ec
+IS - 6
+PY - 2018
+SN - 1748-9326
+SP - 064038
+ST - Targeted policies can compensate most of the increased sustainability risks in 1.5 °C mitigation scenarios
+T2 - Environmental Research Letters
+TI - Targeted policies can compensate most of the increased sustainability risks in 1.5 °C mitigation scenarios
+VL - 13
+ID - 11
+ER -
+
+
+TY - JOUR
+AB - Scenarios that limit global warming to 1.5 °C describe major transformations in energy supply and ever-rising energy demand. Here, we provide a contrasting perspective by developing a narrative of future change based on observable trends that results in low energy demand. We describe and quantify changes in activity levels and energy intensity in the global North and global South for all major energy services. We project that global final energy demand by 2050 reduces to 245 EJ, around 40% lower than today, despite rises in population, income and activity. Using an integrated assessment modelling framework, we show how changes in the quantity and type of energy services drive structural change in intermediate and upstream supply sectors (energy and land use). Down-sizing the global energy system dramatically improves the feasibility of a low-carbon supply-side transformation. Our scenario meets the 1.5 °C climate target as well as many sustainable development goals, without relying on negative emission technologies.
+AU - Grubler, Arnulf
+AU - Wilson, Charlie
+AU - Bento, Nuno
+AU - Boza-Kiss, Benigna
+AU - Krey, Volker
+AU - McCollum, David L.
+AU - Rao, Narasimha D.
+AU - Riahi, Keywan
+AU - Rogelj, Joeri
+AU - De Stercke, Simon
+AU - Cullen, Jonathan
+AU - Frank, Stefan
+AU - Fricko, Oliver
+AU - Guo, Fei
+AU - Gidden, Matt
+AU - Havlík, Petr
+AU - Huppmann, Daniel
+AU - Kiesewetter, Gregor
+AU - Rafaj, Peter
+AU - Schoepp, Wolfgang
+AU - Valin, Hugo
+DO - 10.1038/s41560-018-0172-6
+IS - 6
+PY - 2018
+SN - 2058-7546
+SP - 515-527
+ST - A low energy demand scenario for meeting the 1.5 °C target and sustainable development goals without negative emission technologies
+T2 - Nature Energy
+TI - A low energy demand scenario for meeting the 1.5 °C target and sustainable development goals without negative emission technologies
+VL - 3
+ID - 12
+ER -
+
+
+TY - JOUR
+AB - Mitigation scenarios to limit global warming to 1.5 °C or less in 2100 often rely on large amounts of carbon dioxide removal (CDR), which carry significant potential social, environmental, political and economic risks. A precautionary approach to scenario creation is therefore indicated. This letter presents the results of such a precautionary modelling exercise in which the models C-ROADS and En-ROADS were used to generate a series of 1.5 °C mitigation scenarios that apply increasingly stringent constraints on the scale and type of CDR available. This allows us to explore the trade-offs between near-term stringency of emission reductions and assumptions about future availability of CDR. In particular, we find that regardless of CDR assumptions, near-term ambition increase (‘ratcheting’) is required for any 1.5 °C pathway, making this letter timely for the facilitative, or Talanoa, dialogue to be conducted by the UNFCCC in 2018. By highlighting the difference between net and gross reduction rates, often obscured in scenarios, we find that mid-term gross CO 2 emission reduction rates in scenarios with CDR constraints increase to levels without historical precedence. This in turn highlights, in addition to the need to substantially increase CO 2 reduction rates, the need to improve emission reductions for non-CO 2 greenhouse gases. Further, scenarios in which all or part of the CDR is implemented as non-permanent storage exhibit storage loss emissions, which partly offset CDR, highlighting the importance of differentiating between net and gross CDR in scenarios. We find in some scenarios storage loss trending to similar values as gross CDR, indicating that gross CDR would have to be maintained simply to offset the storage losses of CO 2 sequestered earlier, without any additional net climate benefit.
+AU - Holz, Christian
+AU - Siegel, Lori S.
+AU - Johnston, Eleanor
+AU - Jones, Andrew P.
+AU - Sterman, Jones
+DO - 10.1088/1748-9326/aac0c1
+IS - 6
+PY - 2018
+SN - 1748-9326
+SP - 064028
+ST - Ratcheting ambition to limit warming to 1.5 °C–trade-offs between emission reductions and carbon dioxide removal
+T2 - Environmental Research Letters
+TI - Ratcheting ambition to limit warming to 1.5 °C–trade-offs between emission reductions and carbon dioxide removal
+VL - 13
+ID - 13
+ER -
+
+
+TY - DBASE
+AU - Huppmann, Daniel
+AU - Kriegler, Elmar
+AU - Krey, Volker
+AU - Riahi, Keywan
+AU - Rogelj, Joeri
+AU - Rose, Steven K.
+AU - Weyant, John
+AU - Bauer, Nico
+AU - Bertram, Christoph
+AU - Bosetti, Valentina
+AU - Calvin, Katherine
+AU - Doelman, Jonathan
+AU - Drouet, Laurent
+AU - Emmerling, Johannes
+AU - Frank, Stefan
+AU - Fujimori, Shinichiro
+AU - Gernaat, David
+AU - Grubler, Arnulf
+AU - Guivarch, Celine
+AU - Haigh, Martin
+AU - Holz, Christian
+AU - Iyer, Gokul
+AU - Kato, Etsushi
+AU - Keramidas, Kimon
+AU - Kitous, Alban
+AU - Leblanc, Florian
+AU - Liu, Jing-Yu
+AU - Löffler, Konstantin
+AU - Luderer, Gunnar
+AU - Marcucci, Adriana
+AU - McCollum, David
+AU - Mima, Silvana
+AU - Popp, Alexander
+AU - Sands, Ronald D.
+AU - Sano, Fuminori
+AU - Strefler, Jessica
+AU - Tsutsui, Junichi
+AU - Van Vuuren, Detlef
+AU - Vrontisi, Zoi
+AU - Wise, Marshall
+AU - Zhang, Runsen
+DO - 10.22022/SR15/08-2018.15429
+PB - Integrated Assessment Modeling Consortium & International Institute for Applied Systems Analysis
+PY - 2018
+TI - IAMC 1.5°C Scenario Explorer and Data hosted by IIASA
+UR - https://data.ene.iiasa.ac.at/iamc-sr15-explorer
+ID - 30
+ER -
+
+
+TY - JOUR
+AU - Huppmann, Daniel
+AU - Rogelj, Joeri
+AU - Krey, Volker
+AU - Kriegler, Elmar
+AU - Riahi, Keywan
+DO - 10.1038/s41558-018-0317-4
+PY - 2018
+ST - A new scenario resource for integrated 1.5 °C research
+T2 - Nature Climate Change
+TI - A new scenario resource for integrated 1.5 °C research
+ID - 3
+ER -
+
+
+TY - GEN
+AU - Huppmann, Daniel
+AU - Rogelj, Joeri
+AU - Kriegler, Elmar
+AU - Mundaca, Luis
+AU - Forster, Piers
+AU - Kobayashi, Shigeki
+AU - Séferian, Roland
+AU - Vilariño, María Virginia
+DO - 10.22022/SR15/08-2018.15428
+PY - 2018
+ST - Scenario analysis notebooks for the IPCC Special Report on Global Warming of 1.5°C
+TI - Scenario analysis notebooks for the IPCC Special Report on Global Warming of 1.5°C
+UR - https://github.com/iiasa/ipcc_sr15_scenario_analysis
+ID - 2
+ER -
+
+
+TY - BOOK
+AU - International Energy Agency
+DO - 10.1787/weo-2017-en
+PY - 2017
+ST - World Energy Outlook 2017
+TI - World Energy Outlook 2017
+UR - https://www.oecd-ilibrary.org/content/publication/weo-2017-en
+ID - 19
+ER -
+
+
+TY - BOOK
+AU - International Energy Agency
+DO - 10.1787/energy_tech-2017-en
+PY - 2017
+ST - Energy Technology Perspectives 2017
+TI - Energy Technology Perspectives 2017
+UR - https://www.oecd-ilibrary.org/content/publication/energy_tech-2017-en
+ID - 20
+ER -
+
+
+TY - JOUR
+AU - Kriegler, Elmar
+AU - Bertram, Christoph
+AU - Kuramochi, Takeshi
+AU - Jakob, Michael
+AU - Pehl, Michaja
+AU - Stevanovic, Miodrag
+AU - Höhne, Niklas
+AU - Luderer, Gunnar
+AU - Minx, Jan C.
+AU - Fekete, Hanna
+AU - Hilaire, Jérôme
+AU - Luna, Lisa
+AU - Popp, Alexander
+AU - Steckel, Jan Christoph
+AU - Sterl, Sebastian
+AU - Yalew, Amsalu
+AU - Dietrich, Jan-Philipp
+AU - Edenhofer, Ottmar
+DO - 10.1088/1748-9326/aac4f1
+IS - 7
+PY - 2018
+SP - 074022
+ST - Short term policies to keep the door open for Paris climate goals
+T2 - Environmental Research Letters
+TI - Short term policies to keep the door open for Paris climate goals
+VL - 13
+ID - 14
+ER -
+
+
+TY - JOUR
+AU - Liu, Jing-Yu
+AU - Fujimori, Shinichiro
+AU - Takahashi, Kiyoshi
+AU - Hasegawa, Tomoko
+AU - Su, Xuanming
+AU - Masui, Toshihiko
+DO - 10.1080/17583004.2018.1477374
+PY - 2018
+SN - 1758-3004
+SP - 1-11
+ST - Socioeconomic factors and future challenges of the goal of limiting the increase in global average temperature to 1.5°C
+T2 - Carbon Management
+TI - Socioeconomic factors and future challenges of the goal of limiting the increase in global average temperature to 1.5°C
+UR - https://doi.org/10.1080/17583004.2018.1477374
+ID - 15
+ER -
+
+
+TY - JOUR
+AB - This paper develops a path for the global energy system up to 2050, presenting a new application of the open-source energy modeling system (OSeMOSYS) to the community. It allows quite disaggregate energy and emission analysis: Global Energy System Model (GENeSYS-MOD) uses a system of linear equations of the energy system to search for lowest-cost solutions for a secure energy supply, given externally defined constraints, mainly in terms of CO2-emissions. The general algebraic modeling system (GAMS) version of OSeMOSYS is updated to the newest version and, in addition, extended and enhanced to include e.g., a modal split for transport, an improved trading system, and changes to storages. The model can be scaled from small-scale applications, e.g., a company, to cover the global energy system. The paper also includes an application of GENeSYS-MOD to analyze decarbonization scenarios at the global level, broken down into 10 regions. Its main focus is on interdependencies between traditionally segregated sectors: electricity, transportation, and heating; which are all included in the model. Model calculations suggests that in order to achieve the 1.5–2 °C target, a combination of renewable energy sources provides the lowest-cost solution, solar photovoltaic being the dominant source. Average costs of electricity generation in 2050 are about 4 €cents/kWh (excluding infrastructure and transportation costs).
+AU - Löffler, Konstantin
+AU - Hainsch, Karlo
+AU - Burandt, Thorsten
+AU - Oei, Pao-Yu
+AU - Kemfert, Claudia
+AU - von Hirschhausen, Christian
+DO - 10.3390/en10101468
+IS - 10
+PY - 2017
+SN - 1996-1073
+SP - 1468
+ST - Designing a Model for the Global Energy System -- GENeSYS-MOD: An Application of the Open-Source Energy Modeling System (OSeMOSYS)
+T2 - Energies
+TI - Designing a Model for the Global Energy System -- GENeSYS-MOD: An Application of the Open-Source Energy Modeling System (OSeMOSYS)
+UR - http://www.mdpi.com/1996-1073/10/10/1468
+VL - 10
+ID - 16
+ER -
+
+
+TY - JOUR
+AB - While the international community aims to limit global warming to below 2 ° C to prevent dangerous climate change, little progress has been made towards a global climate agreement to implement the emissions reductions required to reach this target. We use an integrated energy–economy–climate modeling system to examine how a further delay of cooperative action and technology availability affect climate mitigation challenges. With comprehensive emissions reductions starting after 2015 and full technology availability we estimate that maximum 21st century warming may still be limited below 2 ° C with a likely probability and at moderate economic impacts. Achievable temperature targets rise by up to ∼0.4 ° C if the implementation of comprehensive climate policies is delayed by another 15 years, chiefly because of transitional economic impacts. If carbon capture and storage (CCS) is unavailable, the lower limit of achievable targets rises by up to ∼0.3 ° C. Our results show that progress in international climate negotiations within this decade is imperative to keep the 2 ° C target within reach.
+AU - Luderer, Gunnar
+AU - Pietzcker, Robert C.
+AU - Bertram, Christoph
+AU - Kriegler, Elmar
+AU - Meinshausen, Malte
+AU - Edenhofer, Ottmar
+DO - 10.1088/1748-9326/8/3/034033
+IS - 3
+PY - 2013
+SN - 1748-9326
+SP - 034033
+ST - Economic mitigation challenges: how further delay closes the door for achieving climate targets
+T2 - Environmental Research Letters
+TI - Economic mitigation challenges: how further delay closes the door for achieving climate targets
+UR - http://stacks.iop.org/1748-9326/8/i=3/a=034033
+VL - 8
+ID - 17
+ER -
+
+
+TY - JOUR
+AB - The Paris Agreement—which is aimed at holding global warming well below 2 °C while pursuing efforts to limit it below 1.5 °C—has initiated a bottom-up process of iteratively updating nationally determined contributions to reach these long-term goals. Achieving these goals implies a tight limit on cumulative net CO2 emissions, of which residual CO2 emissions from fossil fuels are the greatest impediment. Here, using an ensemble of seven integrated assessment models (IAMs), we explore the determinants of these residual emissions, focusing on sector-level contributions. Even when strengthened pre-2030 mitigation action is combined with very stringent long-term policies, cumulative residual CO2 emissions from fossil fuels remain at 850–1,150 GtCO2 during 2016–2100, despite carbon prices of US$130–420 per tCO2 by 2030. Thus, 640–950 GtCO2 removal is required for a likely chance of limiting end-of-century warming to 1.5 °C. In the absence of strengthened pre-2030 pledges, long-term CO2 commitments are increased by 160–330 GtCO2, further jeopardizing achievement of the 1.5 °C goal and increasing dependence on CO2 removal.
+AU - Luderer, Gunnar
+AU - Vrontisi, Zoi
+AU - Bertram, Christoph
+AU - Edelenbosch, Oreane Y.
+AU - Pietzcker, Robert C.
+AU - Rogelj, Joeri
+AU - De Boer, Harmen Sytze
+AU - Drouet, Laurent
+AU - Emmerling, Johannes
+AU - Fricko, Oliver
+AU - Fujimori, Shinichiro
+AU - Havlík, Petr
+AU - Iyer, Gokul
+AU - Keramidas, Kimon
+AU - Kitous, Alban
+AU - Pehl, Michaja
+AU - Krey, Volker
+AU - Riahi, Keywan
+AU - Saveyn, Bert
+AU - Tavoni, Massimo
+AU - Van Vuuren, Detlef P.
+AU - Kriegler, Elmar
+DA - 2018/07/01
+DO - 10.1038/s41558-018-0198-6
+IS - 7
+PY - 2018
+SN - 1758-6798
+SP - 626-633
+ST - Residual fossil CO2 emissions in 1.5–2 °C pathways
+T2 - Nature Climate Change
+TI - Residual fossil CO2 emissions in 1.5–2 °C pathways
+UR - https://doi.org/10.1038/s41558-018-0198-6
+VL - 8
+ID - 7
+ER -
+
+
+TY - JOUR
+AB - In this paper, we quantify the energy transition and economic consequences of the long-term targets from the Paris agreement, with a particular focus on the targets of limiting global warming by the end of the century to 2 and 1.5 °C. The study assumes early actions and quantifies the market penetration of low carbon technologies, the emission pathways and the economic costs for an efficient reduction of greenhouse gas (GHG) emissions such that the temperature limit is not exceeded. We evaluate the potential role of direct air capture (DAC) and its impact on policy costs and energy consumption. DAC is a technology that removes emissions directly from the atmosphere contributing to negative carbon emissions. We find that, with our modelling assumptions, limiting global temperature to 1.5 °C is only possible when using DAC. Our results show that the DAC technology can play an important role in realising deep decarbonisation goals and in the reduction of regional and global mitigation costs with stringent targets. DAC acts a substitute to Bio-Energy with Carbon Capture and Storage (BECCS) in the stringent scenarios. For this analysis, we use the model MERGE-ETL, a technology-rich integrated assessment model with endogenous learning.
+AU - Marcucci, Adriana
+AU - Kypreos, Socrates
+AU - Panos, Evangelos
+DO - 10.1007/s10584-017-2051-8
+IS - 2
+PY - 2017
+SP - 181-193
+ST - The road to achieving the long-term Paris targets: energy transition and the role of direct air capture
+T2 - Climatic Change
+TI - The road to achieving the long-term Paris targets: energy transition and the role of direct air capture
+VL - 144
+ID - 18
+ER -
+
+
+TY - JOUR
+AB - Low-carbon investments are necessary for driving the energy system transformation that is called for by both the Paris Agreement and Sustainable Development Goals. Improving understanding of the scale and nature of these investments under diverging technology and policy futures is therefore of great importance to decision makers. Here, using six global modelling frameworks, we show that the pronounced reallocation of the investment portfolio required to transform the energy system will not be initiated by the current suite of countries’ Nationally Determined Contributions. Charting a course toward ‘well below 2 °C’ instead sees low-carbon investments overtaking fossil investments globally by around 2025 or before and growing thereafter. Pursuing the 1.5 °C target demands a marked upscaling in low-carbon capital beyond that of a 2 °C-consistent future. Actions consistent with an energy transformation would increase the costs of achieving the goals of energy access and food security, but reduce the costs of achieving air-quality goals.
+AU - McCollum, David L.
+AU - Zhou, Wenji
+AU - Bertram, Christoph
+AU - de Boer, Harmen-Sytze
+AU - Bosetti, Valentina
+AU - Busch, Sebastian
+AU - Després, Jacques
+AU - Drouet, Laurent
+AU - Emmerling, Johannes
+AU - Fay, Marianne
+AU - Fricko, Oliver
+AU - Fujimori, Shinichiro
+AU - Gidden, Matthew
+AU - Harmsen, Mathijs
+AU - Huppmann, Daniel
+AU - Iyer, Gokul
+AU - Krey, Volker
+AU - Kriegler, Elmar
+AU - Nicolas, Claire
+AU - Pachauri, Shonali
+AU - Parkinson, Simon
+AU - Poblete-Cazenave, Miguel
+AU - Rafaj, Peter
+AU - Rao, Narasimha
+AU - Rozenberg, Julie
+AU - Schmitz, Andreas
+AU - Schoepp, Wolfgang
+AU - van Vuuren, Detlef
+AU - Riahi, Keywan
+DO - 10.1038/s41560-018-0179-z
+IS - 7
+PY - 2018
+SN - 2058-7546
+SP - 589-599
+ST - Energy investment needs for fulfilling the Paris Agreement and achieving the Sustainable Development Goals
+T2 - Nature Energy
+TI - Energy investment needs for fulfilling the Paris Agreement and achieving the Sustainable Development Goals
+VL - 3
+ID - 9
+ER -
+
+
+TY - JOUR
+AB - This paper presents the overview of the Shared Socioeconomic Pathways (SSPs) and their energy, land use, and emissions implications. The SSPs are part of a new scenario framework, established by the climate change research community in order to facilitate the integrated analysis of future climate impacts, vulnerabilities, adaptation, and mitigation. The pathways were developed over the last years as a joint community effort and describe plausible major global developments that together would lead in the future to different challenges for mitigation and adaptation to climate change. The SSPs are based on five narratives describing alternative socio-economic developments, including sustainable development, regional rivalry, inequality, fossil-fueled development, and middle-of-the-road development. The long-term demographic and economic projections of the SSPs depict a wide uncertainty range consistent with the scenario literature. A multi-model approach was used for the elaboration of the energy, land-use and the emissions trajectories of SSP-based scenarios. The baseline scenarios lead to global energy consumption of 400–1200 EJ in 2100, and feature vastly different land-use dynamics, ranging from a possible reduction in cropland area up to a massive expansion by more than 700 million hectares by 2100. The associated annual CO2 emissions of the baseline scenarios range from about 25 GtCO2 to more than 120 GtCO2 per year by 2100. With respect to mitigation, we find that associated costs strongly depend on three factors: (1) the policy assumptions, (2) the socio-economic narrative, and (3) the stringency of the target. The carbon price for reaching the target of 2.6 W/m2 that is consistent with a temperature change limit of 2 °C, differs in our analysis thus by about a factor of three across the SSP marker scenarios. Moreover, many models could not reach this target from the SSPs with high mitigation challenges. While the SSPs were designed to represent different mitigation and adaptation challenges, the resulting narratives and quantifications span a wide range of different futures broadly representative of the current literature. This allows their subsequent use and development in new assessments and research projects. Critical next steps for the community scenario process will, among others, involve regional and sectoral extensions, further elaboration of the adaptation and impacts dimension, as well as employing the SSP scenarios with the new generation of earth system models as part of the 6th climate model intercomparison project (CMIP6).
+AU - Riahi, Keywan
+AU - van Vuuren, Detlef P.
+AU - Kriegler, Elmar
+AU - Edmonds, Jae
+AU - O’Neill, Brian C.
+AU - Fujimori, Shinichiro
+AU - Bauer, Nico
+AU - Calvin, Katherine
+AU - Dellink, Rob
+AU - Fricko, Oliver
+AU - Lutz, Wolfgang
+AU - Popp, Alexander
+AU - Cuaresma, Jesus Crespo
+AU - Kc, Samir
+AU - Leimbach, Marian
+AU - Jiang, Leiwen
+AU - Kram, Tom
+AU - Rao, Shilpa
+AU - Emmerling, Johannes
+AU - Ebi, Kristie
+AU - Hasegawa, Tomoko
+AU - Havlik, Petr
+AU - Humpenöder, Florian
+AU - Da Silva, Lara Aleluia
+AU - Smith, Steve
+AU - Stehfest, Elke
+AU - Bosetti, Valentina
+AU - Eom, Jiyong
+AU - Gernaat, David
+AU - Masui, Toshihiko
+AU - Rogelj, Joeri
+AU - Strefler, Jessica
+AU - Drouet, Laurent
+AU - Krey, Volker
+AU - Luderer, Gunnar
+AU - Harmsen, Mathijs
+AU - Takahashi, Kiyoshi
+AU - Baumstark, Lavinia
+AU - Doelman, Jonathan C.
+AU - Kainuma, Mikiko
+AU - Klimont, Zbigniew
+AU - Marangoni, Giacomo
+AU - Lotze-Campen, Hermann
+AU - Obersteiner, Michael
+AU - Tabeau, Andrzej
+AU - Tavoni, Massimo
+DO - 10.1016/j.gloenvcha.2016.05.009
+KW - Shared Socioeconomic Pathways
+SSP
+Climate change
+RCP
+Community scenarios
+Mitigation
+Adaptation
+PY - 2017
+SN - 0959-3780
+SP - 153-168
+ST - The Shared Socioeconomic Pathways and their energy, land use, and greenhouse gas emissions implications: An overview
+T2 - Global Environmental Change
+TI - The Shared Socioeconomic Pathways and their energy, land use, and greenhouse gas emissions implications: An overview
+VL - 42
+ID - 5
+ER -
+
+
+TY - JOUR
+AU - Rogelj, Joeri
+AU - Luderer, Gunnar
+AU - Pietzcker, Robert C.
+AU - Kriegler, Elmar
+AU - Schaeffer, Michiel
+AU - Krey, Volker
+AU - Riahi, Keywan
+DO - 10.1038/nclimate2572
+IS - 6
+M3 - Perspective
+PY - 2015
+SP - 519-527
+ST - Energy system transformations for limiting end-of-century warming to below 1.5 °C
+T2 - Nature Climate Change
+TI - Energy system transformations for limiting end-of-century warming to below 1.5 °C
+UR - http://dx.doi.org/10.1038/nclimate2572
+VL - 5
+ID - 23
+ER -
+
+
+TY - JOUR
+AU - Rogelj, Joeri
+AU - McCollum, David L.
+AU - O’Neill, Brian C.
+AU - Riahi, Keywan
+DO - 10.1038/nclimate1758
+PY - 2013
+SP - 405-412
+ST - 2020 emissions levels required to limit warming to below 2°C
+T2 - Nature Climate Change
+TI - 2020 emissions levels required to limit warming to below 2°C
+UR - http://dx.doi.org/10.1038/nclimate1758
+VL - 3
+ID - 25
+ER -
+
+
+TY - JOUR
+AU - Rogelj, Joeri
+AU - McCollum, David L.
+AU - Reisinger, Andy
+AU - Meinshausen, Malte
+AU - Riahi, Keywan
+DO - 10.1038/nature11787
+PY - 2013
+SP - 79-83
+ST - Probabilistic cost estimates for climate change mitigation
+T2 - Nature
+TI - Probabilistic cost estimates for climate change mitigation
+VL - 493
+ID - 21
+ER -
+
+
+TY - JOUR
+AB - The 2015 Paris Agreement calls for countries to pursue efforts to limit global-mean temperature rise to 1.5 °C. The transition pathways that can meet such a target have not, however, been extensively explored. Here we describe scenarios that limit end-of-century radiative forcing to 1.9 W m−2, and consequently restrict median warming in the year 2100 to below 1.5 °C. We use six integrated assessment models and a simple climate model, under different socio-economic, technological and resource assumptions from five Shared Socio-economic Pathways (SSPs). Some, but not all, SSPs are amenable to pathways to 1.5 °C. Successful 1.9 W m−2 scenarios are characterized by a rapid shift away from traditional fossil-fuel use towards large-scale low-carbon energy supplies, reduced energy use, and carbon-dioxide removal. However, 1.9 W m−2 scenarios could not be achieved in several models under SSPs with strong inequalities, high baseline fossil-fuel use, or scattered short-term climate policy. Further research can help policy-makers to understand the real-world implications of these scenarios.
+AU - Rogelj, Joeri
+AU - Popp, Alexander
+AU - Calvin, Katherine V.
+AU - Luderer, Gunnar
+AU - Emmerling, Johannes
+AU - Gernaat, David
+AU - Fujimori, Shinichiro
+AU - Strefler, Jessica
+AU - Hasegawa, Tomoko
+AU - Marangoni, Giacomo
+AU - Krey, Volker
+AU - Kriegler, Elmar
+AU - Riahi, Keywan
+AU - van Vuuren, Detlef P.
+AU - Doelman, Jonathan
+AU - Drouet, Laurent
+AU - Edmonds, Jae
+AU - Fricko, Oliver
+AU - Harmsen, Mathijs
+AU - Havlík, Petr
+AU - Humpenöder, Florian
+AU - Stehfest, Elke
+AU - Tavoni, Massimo
+DO - 10.1038/s41558-018-0091-3
+PY - 2018
+SN - 1758-6798
+SP - 325-332
+ST - Scenarios towards limiting global mean temperature increase below 1.5 °C
+T2 - Nature Climate Change
+TI - Scenarios towards limiting global mean temperature increase below 1.5 °C
+VL - 8
+ID - 6
+ER -
+
+
+TY - CHAP
+AU - Rogelj, Joeri
+AU - Shindell, Drew
+AU - Jiang, Kejun
+AU - Fifita, Solomone
+AU - Forster, Piers
+AU - Ginzburg, Veronika
+AU - Handa, Collins
+AU - Kheshgi, Haroon
+AU - Kobayashi, Shigeki
+AU - Kriegler, Elmar
+AU - Mundaca, Luis
+AU - Séférian, Roland
+AU - Vilariño, Mario V.
+CY - Geneva
+PB - Intergovernmental Panel on Climate Change
+PY - 2018
+ST - Mitigation pathways compatible with 1.5°C in the context of sustainable development
+T2 - Special Report on the impacts of global warming of 1.5 °C
+TI - Mitigation pathways compatible with 1.5°C in the context of sustainable development
+UR - http://www.ipcc.ch/report/sr15/
+ID - 1
+ER -
+
+
+TY - BOOK
+AU - Shell
+PB - Shell International B.V.
+PY - 2018
+ST - Meeting the goals of the Paris Agreement
+TI - Meeting the goals of the Paris Agreement
+ID - 26
+ER -
+
+
+TY - JOUR
+AB - There are major concerns about the sustainability of large-scale deployment of carbon dioxide removal (CDR) technologies. It is therefore an urgent question to what extent CDR will be needed to implement the long term ambition of the Paris Agreement. Here we show that ambitious near term mitigation significantly decreases CDR requirements to keep the Paris climate targets within reach. Following the nationally determined contributions (NDCs) until 2030 makes 2 °C unachievable without CDR. Reducing 2030 emissions by 20% below NDC levels alleviates the trade-off between high transitional challenges and high CDR deployment. Nevertheless, transitional challenges increase significantly if CDR is constrained to less than 5 Gt CO 2 a −1 in any year. At least 8 Gt CO 2 a −1 CDR are necessary in the long term to achieve 1.5 °C and more than 15 Gt CO 2 a −1 to keep transitional challenges in bounds.
+AU - Strefler, Jessica
+AU - Bauer, Nico
+AU - Kriegler, Elmar
+AU - Popp, Alexander
+AU - Giannousakis, Anastasis
+AU - Edenhofer, Ottmar
+DO - 10.1088/1748-9326/aab2ba
+IS - 4
+PY - 2018
+SN - 1748-9326
+SP - 044015
+ST - Between Scylla and Charybdis: Delayed mitigation narrows the passage between large-scale CDR and high costs
+T2 - Environmental Research Letters
+TI - Between Scylla and Charybdis: Delayed mitigation narrows the passage between large-scale CDR and high costs
+UR - http://stacks.iop.org/1748-9326/13/i=4/a=044015
+VL - 13
+ID - 27
+ER -
+
+
+TY - JOUR
+AB - Mitigation scenarios that achieve the ambitious targets included in the Paris Agreement typically rely on greenhouse gas emission reductions combined with net carbon dioxide removal (CDR) from the atmosphere, mostly accomplished through large-scale application of bioenergy with carbon capture and storage, and afforestation. However, CDR strategies face several difficulties such as reliance on underground CO2 storage and competition for land with food production and biodiversity protection. The question arises whether alternative deep mitigation pathways exist. Here, using an integrated assessment model, we explore the impact of alternative pathways that include lifestyle change, additional reduction of non-CO2 greenhouse gases and more rapid electrification of energy demand based on renewable energy. Although these alternatives also face specific difficulties, they are found to significantly reduce the need for CDR, but not fully eliminate it. The alternatives offer a means to diversify transition pathways to meet the Paris Agreement targets, while simultaneously benefiting other sustainability goals.
+AU - van Vuuren, Detlef P.
+AU - Stehfest, Elke
+AU - Gernaat, David E. H. J.
+AU - van den Berg, Maarten
+AU - Bijl, David L.
+AU - de Boer, Harmen Sytze
+AU - Daioglou, Vassilis
+AU - Doelman, Jonathan C.
+AU - Edelenbosch, Oreane Y.
+AU - Harmsen, Mathijs
+AU - Hof, Andries F.
+AU - van Sluisveld, Mariësse A. E.
+DO - 10.1038/s41558-018-0119-8
+IS - 5
+PY - 2018
+SN - 1758-6798
+SP - 391-397
+ST - Alternative pathways to the 1.5 °C target reduce the need for negative emission technologies
+T2 - Nature Climate Change
+TI - Alternative pathways to the 1.5 °C target reduce the need for negative emission technologies
+UR - https://doi.org/10.1038/s41558-018-0119-8
+VL - 8
+ID - 28
+ER -
+
+
+TY - JOUR
+AB - The Paris Agreement is a milestone in international climate policy as it establishes a global mitigation framework towards 2030 and sets the ground for a potential 1.5 °C climate stabilization. To provide useful insights for the 2018 UNFCCC Talanoa facilitative dialogue, we use eight state-of-the-art climate-energy-economy models to assess the effectiveness of the Intended Nationally Determined Contributions (INDCs) in meeting high probability 1.5 and 2 °C stabilization goals. We estimate that the implementation of conditional INDCs in 2030 leaves an emissions gap from least cost 2 °C and 1.5 °C pathways for year 2030 equal to 15.6 (9.0–20.3) and 24.6 (18.5–29.0) GtCO 2 eq respectively. The immediate transition to a more efficient and low-carbon energy system is key to achieving the Paris goals. The decarbonization of the power supply sector delivers half of total
+AU - Vrontisi, Zoi
+AU - Luderer, Gunnar
+AU - Saveyn, Bert
+AU - Keramidas, Kimon
+AU - Reis, Lara Aleluia
+AU - Baumstark, Lavinia
+AU - Bertram, Christoph
+AU - Sytze de, Harmen Boer
+AU - Drouet, Laurent
+AU - Fragkiadakis, Kostas
+AU - Fricko, Oliver
+AU - Fujimori, Shinichiro
+AU - Guivarch, Celine
+AU - Kitous, Alban
+AU - Krey, Volker
+AU - Kriegler, Elmar
+AU - Ó Broin, Eoin
+AU - Paroussos, Leonidas
+AU - van Vuuren, Detlef
+DO - 10.1088/1748-9326/aab53e
+IS - 4
+PY - 2018
+SN - 1748-9326
+SP - 044039
+ST - Enhancing global climate policy ambition towards a 1.5 °C stabilization: a short-term multi-model assessment
+T2 - Environmental Research Letters
+TI - Enhancing global climate policy ambition towards a 1.5 °C stabilization: a short-term multi-model assessment
+UR - http://stacks.iop.org/1748-9326/13/i=4/a=044039
+VL - 13
+ID - 8
+ER -
+
+
+TY - JOUR
+AB - The transport sector contributes around a quarter of global CO 2 emissions; thus, low-carbon transport policies are required to achieve the 2 °C and 1.5 °C targets. In this paper, representative transport policy scenarios are structured with the aim of achieving a better understanding of the interaction between the transport sector and the macroeconomy. To accomplish this, the Asia–Pacific Integrated Model/Transport (AIM/Transport) model, coupled with a computable general equilibrium model (AIM/CGE), is used to simulate the potential for different transport policy interventions to reduce emissions and cost over the period 2005–2100. The results show that deep decarbonization in the transport sector can be achieved by implementing transport policies such as energy efficiency improvements, vehicle technology innovations particularly the deployment of electric vehicles, public transport developments, and increasing the car occupancy rate. Technological transformations such as vehicle technological innovations and energy efficiency improvements provide the most significant reduction potential. The key finding is that low-carbon transport policies can reduce the carbon price, gross domestic product loss rate, and welfare loss rate generated by climate mitigation policies to limit global warming to 2 °C and 1.5 °C. Interestingly, the contribution of transport policies is more effective for stringent climate change targets in the 1.5 °C scenario, which implies that the stronger the mitigation intensity, the more transport specific policy is required. The transport sector requires attention to achieve the goal of stringent climate change mitigation.
+AU - Zhang, Runsen
+AU - Fujimori, Shinichiro
+AU - Hanaoka, Tatsuya
+DO - 10.1088/1748-9326/aabb0d
+IS - 5
+PY - 2018
+SN - 1748-9326
+SP - 054008
+ST - The contribution of transport policies to the mitigation potential and cost of 2 °C and 1.5 °C goals
+T2 - Environmental Research Letters
+TI - The contribution of transport policies to the mitigation potential and cost of 2 °C and 1.5 °C goals
+UR - http://stacks.iop.org/1748-9326/13/i=5/a=054008
+VL - 13
+ID - 29
+ER -
+
+
diff --git a/data/README.md b/data/README.md
new file mode 100644
index 0000000..bed43e5
--- /dev/null
+++ b/data/README.md
@@ -0,0 +1,22 @@
+# Data folder
+
+This is the folder for all data to be imported and analysed
+for the IPCC SR1.5 scenario assessment.
+The data must be saved as an IAMC-style `csv` or `xlsx` file.
+
+## Scenario ensemble download
+
+The scenario ensemble used for this assessment is available for download
+at [data.ene.iiasa.ac.at/iamc-1.5c-explorer](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer).
+
+The scenario data is licensed under a derivative of the Creative Commons CC-BY 4.0 License.
+If appropriate reference is made to the data source, it is permitted to use
+the data for scientific research and science communication.
+However, redistribution of substantial portions of the data is restricted.
+
+Please read the guidelines and legal code
+at [data.ene.iiasa.ac.at/iamc-1.5c-explorer/#/license](https://data.ene.iiasa.ac.at/iamc-1.5c-explorer/#/license)
+before redistributing this data or adapted material.
+
+When using the scenario data for any analysis, figures or tables,
+please clearly state the release version of the scenario ensemble.
diff --git a/ncc/README.md b/ncc/README.md
new file mode 100644
index 0000000..f7b38a4
--- /dev/null
+++ b/ncc/README.md
@@ -0,0 +1,24 @@
+# Figure for Huppmann et al., Nature Climate Change, 2018
+
+## Overview
+
+This folder contains a notebook for generating the panels of Figure 1
+in [Huppmann et al. (2018)](https://doi.org/10.1038/s41558-018-0317-4),
+see full reference below. The icons used in panel a and references to their
+creators are included in the folder [icons](icons).
+
+## Recommended citation
+
+Please cite the commentary in Nature Climate Change as:
+
+> Daniel Huppmann, Joeri Rogelj, Elmar Kriegler, Volker Krey, and Keywan Riahi.
+> A new scenario resource for integrated 1.5 °C research.
+> *Nature Climate Change*, 2018.
+> doi: [10.1038/s41558-018-0317-4](https://doi.org/10.1038/s41558-018-0317-4)
+
+When using this notebook, please use the citation for this repository
+described in the [README](../README.md).
+
+Both references are included in this repository
+in [Endnote (ris)](../bibliography/iamc_15c.ris)
+or [BibTex (bib)](../bibliography/iamc_15c.bib) format.
diff --git a/ncc/icons/README.md b/ncc/icons/README.md
new file mode 100644
index 0000000..535b7a8
--- /dev/null
+++ b/ncc/icons/README.md
@@ -0,0 +1,12 @@
+# Acknowledgement of icons
+
+The icons used in the figure of the Nature Climate Change commentary
+are from taken from the `Noun Project` (www.thenounproject.com),
+distributed under a Creative Commons CC-BY License.
+
+ - Megaphone (id 1769738) by Creative Stall, PK
+ - Upload (id 874659) by Kimmi Studio
+ - Verification (id 1654894) by joeartcon
+ - Database (id 175016) by Creative Stall, PK
+ - Search (id 176556) by Luis Prado, US
+ - Science Teacher (id 170457) by TukTuk Design
diff --git a/ncc/icons/noun_Database_175016.svg b/ncc/icons/noun_Database_175016.svg
new file mode 100644
index 0000000..1d87f48
--- /dev/null
+++ b/ncc/icons/noun_Database_175016.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ncc/icons/noun_Megaphone_1769738.svg b/ncc/icons/noun_Megaphone_1769738.svg
new file mode 100644
index 0000000..1e0a64c
--- /dev/null
+++ b/ncc/icons/noun_Megaphone_1769738.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ncc/icons/noun_Science Teacher_170457.svg b/ncc/icons/noun_Science Teacher_170457.svg
new file mode 100644
index 0000000..90057eb
--- /dev/null
+++ b/ncc/icons/noun_Science Teacher_170457.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ncc/icons/noun_Search_176556.svg b/ncc/icons/noun_Search_176556.svg
new file mode 100644
index 0000000..385e043
--- /dev/null
+++ b/ncc/icons/noun_Search_176556.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ncc/icons/noun_Upload_874659.svg b/ncc/icons/noun_Upload_874659.svg
new file mode 100644
index 0000000..e62805a
--- /dev/null
+++ b/ncc/icons/noun_Upload_874659.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ncc/icons/noun_Verification_1654894.svg b/ncc/icons/noun_Verification_1654894.svg
new file mode 100644
index 0000000..f2dc3c5
--- /dev/null
+++ b/ncc/icons/noun_Verification_1654894.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ncc/ncc_figure.ipynb b/ncc/ncc_figure.ipynb
new file mode 100644
index 0000000..b6118f4
--- /dev/null
+++ b/ncc/ncc_figure.ipynb
@@ -0,0 +1,528 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### *Nature Climate Change Commentary on the IPCC SR1.5 scenario resource*\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# An overview of the *IAMC 1.5°C scenario ensemble*\n",
+ "\n",
+ "This notebook generates the figure in the commentary published in *Nature Climate Change*\n",
+ "on the scenario resource compiled for the IPCC's _\"Special Report on Global Warming of 1.5°C\"_.\n",
+ "\n",
+ "The scenario ensemble can be accessed at https://data.ene.iiasa.ac.at/iamc-1.5c-explorer.\n",
+ "\n",
+ "#### License and recommended citation\n",
+ "\n",
+ "This notebook is licensed under the APACHE 2.0 License. Please read the [NOTICE](NOTICE) for more information.\n",
+ "\n",
+ "When using this notebook, please cite as:\n",
+ "\n",
+ "> Daniel Huppmann et al.,\n",
+ "> Scenario analysis notebooks for the IPCC Special Report on of Global Warming of 1.5°C. 2018 \n",
+ "> doi: [10.22022/SR15/08-2018.15428](https://doi.org/10.22022/SR15/08-2018.15428) |\n",
+ "> url: [github.com/iiasa/ipcc_sr15_scenario_analysis](https://github.com/iiasa/ipcc_sr15_scenario_analysis)\n",
+ "\n",
+ "You can download the recommended citations as [Endnote (ris)](../bibliography/iamc_15c.ris)\n",
+ "or [BibTex (bib)](../bibliography/iamc_15c.bib) format."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Load required packages, import data and metadata\n",
+ "\n",
+ "The metadata file should have been generated from the notebook ``sr1p5_categories_indicators`` included in this repository. \n",
+ "If the snapshot file has been updated, make sure that you have an up-to-date metadata file.\n",
+ "\n",
+ "The last cell of this section loads and assigns a number of auxiliary lists and the `run_control` specifications as defined in the categories-indicators notebook. The imported dictionary `specs` should be empty after popping all relevant data."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import warnings\n",
+ "import io\n",
+ "import itertools\n",
+ "import yaml\n",
+ "import math\n",
+ "import matplotlib.pyplot as plt\n",
+ "%matplotlib inline\n",
+ "import pyam"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5 = pyam.IamDataFrame(data='../data/iamc15_world_public_release_v0.csv')\n",
+ "sr1p5.filter(region='World', inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sr1p5.load_metadata('../analysis/sr1p5_metadata_indicators.xlsx')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(\"../analysis/sr1p5_specs.yaml\", 'r') as stream:\n",
+ " specs = yaml.load(stream)\n",
+ "\n",
+ "rc = pyam.run_control()\n",
+ "for item in specs.pop('run_control').items():\n",
+ " rc.update({item[0]: item[1]})\n",
+ "cats = specs.pop('cats')\n",
+ "all_cats = specs.pop('all_cats')\n",
+ "subcats = specs.pop('subcats')\n",
+ "all_subcats = specs.pop('all_subcats')\n",
+ "plotting_args = specs.pop('plotting_args')\n",
+ "marker= specs.pop('marker')\n",
+ "\n",
+ "specs"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Filter for valid scenarios\n",
+ "\n",
+ "Only include relevant scenarios in the analysis."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "full_century = range(2000, 2101, 10)\n",
+ "horizon = range(2010, 2101, 10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sr1p5.filter(category=cats, year=full_century, exclude=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plots of drivers"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pop = df.filter(variable='Population')\n",
+ "pop.convert_unit({'million': ('billion', 0.001)}, inplace=True)\n",
+ "\n",
+ "gdp = df.filter(variable='GDP|PPP')\n",
+ "gdp.convert_unit({'billion US$2010/yr': ('trillion US$2010/yr', 0.001)}, inplace=True)\n",
+ "\n",
+ "primary = df.filter(variable='Primary Energy')\n",
+ "\n",
+ "forest = df.filter(variable='Land Cover|Forest')\n",
+ "forest.convert_unit({'million ha': ('million km2', 0.01)}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "config = [\n",
+ " (pop, 'Population'),\n",
+ " (gdp, 'Economic output'),\n",
+ " (primary, 'Primary energy'),\n",
+ " (forest, 'Forest cover')\n",
+ "]\n",
+ "\n",
+ "drivers, _ax = plt.subplots(1, 4, figsize=(11, 2))\n",
+ "\n",
+ "for i, (_df, title) in enumerate(config):\n",
+ " \n",
+ " _df = _df.filter(year=horizon)\n",
+ " data = _df.timeseries()\n",
+ " data = data[data[2020] > 1]\n",
+ " _min = data.quantile(q=0)\n",
+ " _max = data.quantile(q=1)\n",
+ " _ax[i].stackplot(horizon, _min, _max - _min, colors=['', 'lightgrey'])\n",
+ " \n",
+ " _ax[i] = _df.line_plot(ax=_ax[i], color='lightskyblue', linewidth=0.5, legend=False)\n",
+ " _ax[i].set_title(title)\n",
+ " _ax[i].set_xlabel('')\n",
+ " _ax[i].set_ylabel(_df.data.unit.unique()[0])\n",
+ " _ax[i].set_ylim(0.9 * min(_min), 1.1 * max(_max))\n",
+ "\n",
+ "drivers.tight_layout()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "drivers.savefig('ncc_drivers.eps')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Carbon dioxide emission"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "co2 = df.filter(year=horizon, variable='Emissions|CO2')\n",
+ "co2.convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pyam.run_control()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "emissions, _ax = plt.subplots(1, 2, sharey=True, figsize=(6, 2))\n",
+ "\n",
+ "classes = [\n",
+ " ('1.5C pathways', ['Below 1.5C', '1.5C low OS', '1.5C high OS'], 'xkcd:bluish'),\n",
+ " ('2C pathways', ['Lower 2C', 'Higher 2C'], 'xkcd:orange'),\n",
+ " ('Exceeding 2C', ['Above 2C'], 'lightgrey'),\n",
+ "]\n",
+ "\n",
+ "## settings for axes 2\n",
+ "\n",
+ "years = [2030, 2050, 2100]\n",
+ "ymax = 70\n",
+ "mincount = 7\n",
+ "\n",
+ "_classes = len(classes) - 1\n",
+ "w = 0.6 / _classes\n",
+ "\n",
+ "_ax[1].hlines(0, xmin=-0.5, xmax=(len(years) - 0.5), linewidths=0.6)\n",
+ "\n",
+ "##\n",
+ "\n",
+ "for (name, _cats, c) in reversed(classes):\n",
+ " _co2 = co2.filter(category=_cats).timeseries()\n",
+ " if not _co2.empty:\n",
+ " _min = _co2.quantile(q=0.25)\n",
+ " _max = _co2.quantile(q=0.75)\n",
+ " _med = _co2.apply(lambda x: np.median(x))\n",
+ " _ax[0].stackplot(horizon, _min, _max - _min, colors=['', c])\n",
+ " _ax[0].plot(horizon, _min, color=c, linewidth=0.8)\n",
+ " _ax[0].plot(horizon, _max, color=c, linewidth=0.8)\n",
+ " _ax[0].plot(horizon, _med, color=c, linewidth=2)\n",
+ "\n",
+ "for i, (name, _cats, c) in enumerate(classes):\n",
+ " _co2 = co2.filter(category=_cats).timeseries()\n",
+ " if not _co2.empty:\n",
+ " for j, y in enumerate(years):\n",
+ " lst = _co2[y][~np.isnan(_co2[y])]\n",
+ " pos = (0.75 / _classes * (i - _classes / 2) + j)\n",
+ "\n",
+ " outliers = len(lst[lst > ymax])\n",
+ "# if outliers > 0:\n",
+ "# _ax[1].text(pos - 0.01 * len(years), ymax, outliers)\n",
+ "\n",
+ " if len(lst) >= mincount:\n",
+ " p = _ax[1].boxplot(lst, positions=[pos], widths=w * .90,\n",
+ " whis='range',\n",
+ " patch_artist=True)\n",
+ " plt.setp(p['boxes'], color=c)\n",
+ " plt.setp(p['medians'], color='black')\n",
+ " else:\n",
+ " _ax[1].scatter(x=[pos] * len(lst), y=lst, zorder=5,\n",
+ " c=c, edgecolors='black', marker='o',\n",
+ " s=30, label=None)\n",
+ " _ax[1].plot([pos, pos], [max(lst), min(lst)], zorder=4,\n",
+ " color='black', linewidth=1, linestyle='-',\n",
+ " marker='_', markersize=8, markeredgewidth=1,\n",
+ " markeredgecolor='black')\n",
+ "\n",
+ " _ax[1].plot([], c=c, label='{} [{}]'.format(name, len(_co2)))\n",
+ "\n",
+ "_ax[0].hlines(0, xmin=horizon.start, xmax=horizon.stop - 1, linewidths=0.6)\n",
+ "#_ax[0].set_title('Trajectories by category')\n",
+ "_ax[0].set_ylabel('Gt CO2/yr')\n",
+ "_ax[0].set_ylim(-21, ymax)\n",
+ "\n",
+ "_ax[1].set_position([0.49, 0.124, 0.2, 0.753])\n",
+ "#_ax[1].set_title('Ranges')\n",
+ "_ax[1].set_xlim(-0.6, (len(years) - 0.4))\n",
+ "plt.xticks(range(0, len(years)), years)\n",
+ "\n",
+ "_ax[1].legend()\n",
+ "#emissions.tight_layout()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "emissions.savefig('ncc_carbon_emissions.eps')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Statistical overview of bioenergy and other indicators"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ccs = df.filter(variable='Carbon Sequestration|CCS')\n",
+ "ccs.convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)}, inplace=True)\n",
+ "beccs = df.filter(variable='Carbon Sequestration|CCS|Biomass')\n",
+ "beccs.convert_unit({'Mt CO2/yr': ('Gt CO2/yr', 0.001)}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cum_ccs = ccs.timeseries().apply(pyam.cumulative, raw=False, axis=1, first_year=2020, last_year=2100)\n",
+ "cum_beccs = beccs.timeseries().apply(pyam.cumulative, raw=False, axis=1, first_year=2020, last_year=2100)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ccs_fig, _ax = plt.subplots(2, 2, sharey=True, figsize=(4, 2))\n",
+ "\n",
+ "for i, (_cats, superclass, color) in enumerate([(['Below 1.5C', '1.5C low OS', '1.5C high OS'], '1.5', 'palegreen'),\n",
+ " (['Lower 2C', 'Higher 2C'], '2.0', 'palevioletred')]):\n",
+ "\n",
+ " for j, (data, group, count) in enumerate([(cum_ccs, 'CCS', 20),\n",
+ " (cum_beccs, 'BECCS', 12)]):\n",
+ " groupby = pyam.filter_by_meta(data.reset_index(),df, join_meta=True, category=_cats).groupby('category')\n",
+ "\n",
+ " data = []\n",
+ " color = []\n",
+ " labels = []\n",
+ "\n",
+ " for name in _cats:\n",
+ " x = groupby.get_group(name)\n",
+ " if not x.empty:\n",
+ " data.append(x[0][~np.isnan(x[0])])\n",
+ " color.append(rc['color']['category'][name])\n",
+ " labels.append([name])\n",
+ "\n",
+ " _ax[i][j].hist(data, count, color=color, label=labels, stacked=True)\n",
+ "\n",
+ " if i == 0:\n",
+ " _ax[i][j].set_title(group)\n",
+ " _ax[i][j].set_xticks([])\n",
+ " else:\n",
+ " _ax[1][j].set_xlabel('GtCO2')\n",
+ " _ax[i][0].set_ylabel('Number of \\n {}°C scenarios'.format(superclass))\n",
+ "\n",
+ "_ax[0][1].set_position([0.52, 0.538, 0.2, 0.342])\n",
+ "_ax[1][1].set_position([0.52, 0.124, 0.2, 0.342])"
+ ]
+ },
+ {
+ "cell_type": "raw",
+ "metadata": {},
+ "source": [
+ "ccs_fig.savefig('ncc_ccs_histogram.eps')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Energy system transformation in two illustrative pathways"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "marker = ['LED', 'S5']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ene = sr1p5.filter(marker=marker)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "variable_mapping = [\n",
+ " ('Fossil without CCS', 'Primary Energy|Fossil|w/o CCS', 'black', ''),\n",
+ " ('Fossil with CCS', 'Primary Energy|Fossil|w/ CCS', 'grey', '//'),\n",
+ " ('Biomass without CCS',\n",
+ " ['Primary Energy|Biomass|Modern|w/o CCS',\n",
+ " 'Primary Energy|Biomass|Traditional'], 'forestgreen', ''),\n",
+ " ('Biomass with CCS', 'Primary Energy|Biomass|Modern|w/ CCS', 'limegreen', '//'),\n",
+ " ('Nuclear', 'Primary Energy|Nuclear', 'firebrick', ''),\n",
+ " ('Other renewables',\n",
+ " ['Primary Energy|Ocean',\n",
+ " 'Primary Energy|Geothermal',\n",
+ " 'Primary Energy|Hydro'], 'darkorange', ''),\n",
+ " ('Wind', 'Primary Energy|Wind', 'lightskyblue', ''),\n",
+ " ('Solar', 'Primary Energy|Solar', 'gold', ''),\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "variables = []\n",
+ "mapping = {}\n",
+ "\n",
+ "for (name, variable, color, hatch) in variable_mapping:\n",
+ " variables.append(name)\n",
+ " if isinstance(variable, list):\n",
+ " for v in variable:\n",
+ " mapping.update({v: name})\n",
+ " else:\n",
+ " mapping.update({variable: name})\n",
+ " rc.update({'color': {'variable': {name: color}}})\n",
+ " rc.update({'hatch': {'variable': {name: hatch}}})\n",
+ "\n",
+ "ene.rename({'variable': mapping}, inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "_ene = ene.filter(variable=variables, year=range(2010, 2101, 10))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ene_fig, _ax = plt.subplots(1, len(marker), sharey=True, figsize=(15, 3))\n",
+ "\n",
+ "for i, m in enumerate(marker):\n",
+ " _df = _ene.filter(marker=m)\n",
+ " _df.data.variable = _df.data.variable.astype('category')\n",
+ " _df.data.variable.cat.set_categories(variables, inplace=True)\n",
+ " _df.data.sort_values('variable', inplace=True)\n",
+ " _df.stack_plot(ax=_ax[i], legend=False)\n",
+ " _ax[i].set_title('')\n",
+ " _ax[i].set_xlabel('')\n",
+ " if i > 0:\n",
+ " _ax[i].set_ylabel('')\n",
+ "_ax[0].legend()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ene_fig.savefig('ncc_energy_transitions.eps')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.4"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}