{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Update the electricity supply mix\n",
    "\n",
    "This workflow shows how to overwrite the electricity generation mix of an IOT\n",
    "*database* with up-to-date shares, either derived automatically from\n",
    "[EMBER](https://ember-energy.org/) electricity-generation data or provided\n",
    "explicitly.\n",
    "\n",
    "It applies to any IOT database that exposes a **disaggregated power sector**,\n",
    "i.e. separate generation technologies rather than a single aggregated\n",
    "electricity sector. At the moment these are:\n",
    "\n",
    "* **EXIOBASE** (IOT, monetary), used in the example below;\n",
    "* **EMERGING-E**.\n",
    "\n",
    "MARIO detects the disaggregated generation sectors automatically, so the same\n",
    "call works across the supported databases without extra configuration.\n",
    "\n",
    "Core methods\n",
    "------------\n",
    "\n",
    "The two main entry points are:\n",
    "\n",
    "* `Database.update_supply_mix_iot` to rewrite the mix in place across the\n",
    "  intersectoral (`z`) and final-demand (`Y`) blocks of one scenario;\n",
    "* `Database.get_mix` to read back the current production mix of a sector\n",
    "  bundle as a `region -> {sector: share}` mapping.\n",
    "\n",
    "`Database.update_mix_iot` is kept as a backward-compatible alias of\n",
    "`update_supply_mix_iot`.\n",
    "\n",
    "> **Note:** Both methods are currently implemented for **IOT** tables only."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## What the update does\n",
    "\n",
    "The EMBER taxonomy is more aggregated than the disaggregated electricity\n",
    "sectors exposed by EXIOBASE IOT and EMERGING-E. When you request the\n",
    "`\"electricity\"` mode, MARIO:\n",
    "\n",
    "1. aggregates the database electricity bundle to the compatible EMBER fuel\n",
    "   groups (coal, gas, nuclear, hydro, wind, solar, bioenergy, other\n",
    "   renewables, other fossil);\n",
    "2. reads the EMBER generation shares for the requested `year`;\n",
    "3. redistributes each EMBER group total back to the original database\n",
    "   sectors using the **current internal composition** of each group.\n",
    "\n",
    "This means detailed technologies such as geothermal, tide/wave/ocean and\n",
    "solar thermal are updated only through their parent EMBER group, while\n",
    "transmission and distribution sectors are left unchanged."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## EMBER-based electricity mix\n",
    "\n",
    "Parse an EXIOBASE monetary IOT table (which ships the disaggregated\n",
    "electricity generation sectors) and update the mix for one scenario. When\n",
    "`year` is omitted, MARIO uses the latest year available in the packaged EMBER\n",
    "snapshot."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import mario\n",
    "\n",
    "db = mario.parse_exiobase(\n",
    "    table=\"IOT\",\n",
    "    unit=\"Monetary\",\n",
    "    path=\"/path/to/IOT_2022_ixi.zip\",\n",
    "    name=\"EXIOBASE 3\",\n",
    "    year=2022,\n",
    ")\n",
    "\n",
    "# Rewrite the electricity generation mix of the baseline scenario\n",
    "db.update_supply_mix_iot(\"electricity\", scenario=\"baseline\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Inspect the resulting mix for one region. `get_mix` accepts the special\n",
    "string `\"electricity\"`, which resolves the same generation-sector bundle\n",
    "used by the update. EXIOBASE regions are two-letter codes, e.g. `\"IT\"` for\n",
    "Italy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mix = db.get_mix(\"electricity\", scenario=\"baseline\")\n",
    "mix[\"IT\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Choosing the reference year\n",
    "\n",
    "Pass `year=...` to target a specific EMBER year. When a covered region has no\n",
    "observation for that year, MARIO falls back to the nearest available year for\n",
    "that region and logs the substitution."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "db.update_supply_mix_iot(\"electricity\", scenario=\"baseline\", year=2023)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Creating the scenario on the fly\n",
    "\n",
    "To write the updated mix into a new scenario, pass `clone_from` with an\n",
    "existing source scenario. MARIO clones it first and then applies the update."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "db.update_supply_mix_iot(\n",
    "    \"electricity\",\n",
    "    scenario=\"ember_2025\",\n",
    "    clone_from=\"baseline\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Aggregated regions\n",
    "\n",
    "Aggregate regions are resolved to their underlying countries before the EMBER\n",
    "generation is summed, so no manual bookkeeping is required. This covers two\n",
    "situations:\n",
    "\n",
    "* **Built-in Rest-of-World regions.** EXIOBASE ships aggregate regions such as\n",
    "  `WA` (Rest of the World Asia and Pacific); MARIO expands them to their\n",
    "  packaged member countries automatically.\n",
    "* **User aggregations.** When you cluster countries yourself with `aggregate`\n",
    "  (for example into a `Rest of Europe` region), MARIO reuses the region\n",
    "  aggregation map stored on `db.meta.region_aggregation_map`.\n",
    "\n",
    "If the map is not available (for example when the regions were renamed outside\n",
    "of `aggregate`), pass the concordance explicitly through `region_aggregation`.\n",
    "It accepts the same inputs as `aggregate`: a Region aggregation workbook, a\n",
    "pandas `Series`/`DataFrame`, or a mapping."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "db.update_supply_mix_iot(\n",
    "    \"electricity\",\n",
    "    scenario=\"baseline\",\n",
    "    region_aggregation={\n",
    "        \"Rest of Europe\": [\"FR\", \"DE\", \"ES\", \"IT\"],\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> **Note:** Regions that cannot be matched to the EMBER concordance, that are\n",
    "> missing from the EMBER snapshot, or that report no positive generation are\n",
    "> left unchanged. MARIO reports each of these cases in the logs."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Custom shares\n",
    "\n",
    "Instead of `\"electricity\"`, you can pass an explicit mapping\n",
    "`region -> {sector: share}`. The combined coefficient rows of the selected\n",
    "sectors are redistributed within each region according to the provided\n",
    "weights. Shares are expected to sum to one; pass `rescale=True` to normalise\n",
    "arbitrary positive totals.\n",
    "\n",
    "The sector labels must match those of the database. You can list the available\n",
    "electricity generation sectors from the mix keys:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "list(db.get_mix(\"electricity\")[\"IT\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "shares = {\n",
    "    \"IT\": {\n",
    "        \"Production of electricity by solar photovoltaic\": 0.6,\n",
    "        \"Production of electricity by wind\": 0.4,\n",
    "    },\n",
    "}\n",
    "\n",
    "db.update_supply_mix_iot(shares, scenario=\"baseline\", rescale=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exporting to EMBER groups\n",
    "\n",
    "Set `aggregate_as_ember=True` (only with `\"electricity\"`) to collapse the\n",
    "disaggregated electricity sectors into the compatible EMBER groups right\n",
    "after updating the mix, yielding a database whose electricity taxonomy\n",
    "matches EMBER."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "db.update_supply_mix_iot(\n",
    "    \"electricity\",\n",
    "    scenario=\"baseline\",\n",
    "    aggregate_as_ember=True,\n",
    ")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "mario",
   "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.13.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
