{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "0fec011c",
   "metadata": {},
   "source": [
    "# The openLCA Result API\n",
    "\n",
    "openLCA 2 provides a harmonized result interface that can be called from\n",
    "different APIs (Java, JSON-RPC, gRPC, Rest). All these APIs call the same\n",
    "backend which is implemented in the openLCA kernel. This kernel is independent\n",
    "from the openLCA user interface and can be integrated as a service into other\n",
    "applications.\n",
    "\n",
    "The idea of the result interface is not to provide some ready-to-use charts and\n",
    "tables but to provide all possible building blocks with which such higher level\n",
    "result views can be created (charts, tables, upstream trees, Sankey diagrams).\n",
    "Thus, the result interface has many methods that often look quite similar but\n",
    "they have their purpose for efficiently creating higher level result views. This\n",
    "notebook tries to explain what these methods do with examples using the [openLCA\n",
    "Python IPC API v2](https://github.com/GreenDelta/olca-ipc.py). The calculation\n",
    "is sometimes explained using [standard LCA matrix algebra](.#) but this does mean\n",
    "that the implementation uses exactly these formulas when calculating results."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f62cff94",
   "metadata": {},
   "source": [
    "## Setup\n",
    "\n",
    "In order to run the examples in this document, you need to have the olca-ipc.py\n",
    "module installed and an IPC server in openLCA runnig (`Tools > Developer tools >\n",
    "IPC Server`). First, make sure that the `olca-ipc` and `olca-schema` modules are\n",
    "installed. We also use `pandas` and `matplotlib` for visualisations:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d4f2cfb3",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "!pip list | grep 'olca\\|pandas\\|matplotlib\\|mplcyberpunk'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d74f52b7",
   "metadata": {},
   "source": [
    "Now, we import the required modules and add some boilerplate to make the\n",
    "creation of data frames a bit more convenient below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01eb2b87",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Any, Callable, Iterable, Literal, TypeVar\n",
    "\n",
    "import olca_ipc as ipc\n",
    "import olca_schema as lca\n",
    "import olca_schema.results as res\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import mplcyberpunk\n",
    "\n",
    "plt.style.use(\"cyberpunk\")\n",
    "glow = mplcyberpunk.add_glow_effects\n",
    "\n",
    "E = TypeVar(\"E\")\n",
    "\n",
    "\n",
    "def df(\n",
    "    data: Iterable[Any], *cols: tuple[str, Callable[[E], Any]]\n",
    ") -> pd.DataFrame:\n",
    "    columns = [c[0] for c in cols]\n",
    "    transformed = []\n",
    "    for row in data:\n",
    "        transformed.append([col[1](row) for col in cols])\n",
    "    return pd.DataFrame(transformed, columns=columns)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3978c11e",
   "metadata": {},
   "source": [
    "## Calculation and result state\n",
    "\n",
    "### `/calculate`\n",
    "\n",
    "In order to run a calculation, we first need to create a calculation setup. In\n",
    "this setup, we define the calculation target (a process or product system) and\n",
    "configure options like the LCIA method that should be used, if life cycle costs\n",
    "should be calculated or not, which parameters should be redefined etc. With this\n",
    "setup we can start a calculation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a368246d",
   "metadata": {},
   "outputs": [],
   "source": [
    "setup = res.CalculationSetup(\n",
    "    target=lca.Ref(\n",
    "        model_type=\"ProductSystem\", id=\"7c328e9b-d8e3-402b-a1ac-95620d021b99\"\n",
    "    ),\n",
    "    impact_method=lca.Ref(\n",
    "        model_type=\"ImpactMethod\", id=\"787c02f1-d1f2-36d6-8e06-2307cc3ebebc\"\n",
    "    ),\n",
    ")\n",
    "client = ipc.Client(8080)\n",
    "result = client.calculate(setup)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a0fd107",
   "metadata": {},
   "source": [
    "### `/state`\n",
    "\n",
    "Starting the calculation directly returns a result object but this result may\n",
    "isn't ready yet. This is because when we start a calculation, it is first put in\n",
    "a calculation queue and there may are other calculations that are still running\n",
    "until our calculation is scheduled and then, we may have to wait a bit depending\n",
    "how big the system is we calculate. We can inspect the result state and could\n",
    "actively wait unit the `is_ready` attribute is `True`. The result can also be an\n",
    "error so we should also check this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e9704234",
   "metadata": {},
   "outputs": [],
   "source": [
    "result.get_state()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1b927b02",
   "metadata": {},
   "source": [
    "We can also just use the convenience method `wait_until_ready`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8b0b395d",
   "metadata": {},
   "outputs": [],
   "source": [
    "result.wait_until_ready()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d4a5afd",
   "metadata": {},
   "source": [
    "### `/dispose`\n",
    "We will call the method `dispose` at the end of this notebook but mention it\n",
    "already here: a calculated result can allocate quite some resources in the\n",
    "openLCA backend depending on the calculated system. If we do not need the result\n",
    "anymore, we should dispose the result to free these resources especially, if we\n",
    "want to run multiple calculations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "19324ddc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# we do this later\n",
    "# result.dispose()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5a77024",
   "metadata": {},
   "source": [
    "## Result elements\n",
    "\n",
    "### `/tech-flows`\n",
    "\n",
    "Technosphere flows are the product and waste flows of the product system by\n",
    "which the processes in that system are connected. Each technosphere flow is a\n",
    "pair of a provider and a flow so that the same flow could have different\n",
    "providers (e.g. electricity produced by different processes). Providers are\n",
    "typically processes but could also be sub-systems of the product system or even\n",
    "precalculated results. The technosphere matrix $A$ is symmetrically indexed by\n",
    "these $n$ technosphere flows.\n",
    "\n",
    "$$\n",
    "A \\in \\mathbb{R}^{n \\times n}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d5973ee9",
   "metadata": {},
   "outputs": [],
   "source": [
    "tech_flows = result.get_tech_flows()\n",
    "df(\n",
    "    tech_flows,\n",
    "    (\"Provider\", lambda tf: tf.provider.name),\n",
    "    (\"Flow\", lambda tf: tf.flow.name),\n",
    ").head()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1864172",
   "metadata": {},
   "source": [
    "Results related to technosphere flows are returned as instances of the type\n",
    "[TechFlowValue](http://greendelta.github.io/olca-schema/classes/TechFlowValue.html).\n",
    "We map such results to data frames with the following function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "303c7086",
   "metadata": {},
   "outputs": [],
   "source": [
    "def tech_values(\n",
    "    data: list[res.TechFlowValue],\n",
    "    unit: Callable[\n",
    "        [res.TechFlowValue], Any\n",
    "    ] = lambda v: v.tech_flow.flow.ref_unit,\n",
    "    sort: Literal[\"asc\", \"desc\"] | None = None,\n",
    ") -> pd.DataFrame:\n",
    "    if sort:\n",
    "        data.sort(key=lambda v: v.amount, reverse=sort == \"desc\")\n",
    "    return df(\n",
    "        data,\n",
    "        (\"Provider\", lambda v: v.tech_flow.provider.name),\n",
    "        (\"Flow\", lambda v: v.tech_flow.flow.name),\n",
    "        (\"Amount\", lambda v: v.amount),\n",
    "        (\"Unit\", unit),\n",
    "    )\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c34983f",
   "metadata": {},
   "source": [
    "### `/envi-flows`\n",
    "\n",
    "Intervention flows cross the boundary of the product system (the technosphere)\n",
    "with its environment. The amounts of these flows form the inventory result of\n",
    "the system. These are typically elementary flows but also unlinked products or\n",
    "waste flows could occur here. In case of a regionalized calculation,\n",
    "intervention flows can have locations attached that specify where this\n",
    "intervention (crossing the boundary to the environment) happens. The values of\n",
    "the $m$ intervention flows are stored in the intervention matrix $B$:\n",
    "\n",
    "$$\n",
    "B \\in \\mathbb{R}^{m \\times n}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bb383371",
   "metadata": {},
   "outputs": [],
   "source": [
    "envi_flows = result.get_envi_flows()\n",
    "df(envi_flows,\n",
    "  (\"Is input?\", lambda ef: ef.is_input),\n",
    "  (\"Flow\", lambda ef: ef.flow.name),\n",
    "  (\"Category\", lambda ef: ef.flow.category)).head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "50cc829b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def envi_values(\n",
    "    data: list[res.EnviFlowValue],\n",
    "    unit: Callable[\n",
    "        [res.EnviFlowValue], Any\n",
    "    ] = lambda v: v.envi_flow.flow.ref_unit,\n",
    "    sort: Literal[\"asc\", \"desc\"] | None = None,\n",
    ") -> pd.DataFrame:\n",
    "    if sort:\n",
    "        data.sort(key=lambda v: v.amount, reverse=sort == \"desc\")\n",
    "    return df(\n",
    "        data,\n",
    "        (\"Flow\", lambda v: v.envi_flow.flow.name),\n",
    "        (\"Category\", lambda v: v.envi_flow.flow.category),\n",
    "        (\"Amount\", lambda v: v.amount),\n",
    "        (\"Unit\", unit),\n",
    "    )\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a2c8f1a",
   "metadata": {},
   "source": [
    "### `/impact-categories`\n",
    "\n",
    "Depending on the selected impact assessment method in the calculation setup,\n",
    "there ares $k$ impact categories for which an impact assessment result is\n",
    "calculated. The characterization factors of these $k$ impact categories for the\n",
    "$m$ flows in the system are stored in the impact matrix $C$:\n",
    "\n",
    "$$\n",
    "C \\in \\mathbb{R}^{k \\times n}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d446646",
   "metadata": {},
   "outputs": [],
   "source": [
    "impact_categories = result.get_impact_categories()\n",
    "df(impact_categories, (\"Impact category\", lambda i: i.name))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c3b6362b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def impact_values(\n",
    "    data: list[res.ImpactValue],\n",
    "    unit: Callable[\n",
    "        [res.ImpactValue], Any\n",
    "    ] = lambda v: v.impact_category.ref_unit,\n",
    "    sort: Literal[\"asc\", \"desc\"] | None = None,\n",
    ") -> pd.DataFrame:\n",
    "    if sort:\n",
    "        data.sort(key=lambda v: v.amount, reverse=sort == \"desc\")\n",
    "    return df(\n",
    "        data,\n",
    "        (\"Impact category\", lambda v: v.impact_category.name),\n",
    "        (\"Amount\", lambda v: v.amount),\n",
    "        (\"Unit\", unit),\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92275b6e",
   "metadata": {},
   "source": [
    "## Technosphere flows"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3421c9ee",
   "metadata": {},
   "source": [
    "### `/total-requirements`\n",
    "\n",
    "This method returns the total requirements $t$ of technosphere flows to\n",
    "fulfill the demand of a product system. The amounts are given in the respective\n",
    "reference units of the technosphere flows. $t$ can be calculated by scaling the\n",
    "diagonal of the technosphere matrix $A$ with the scaling vector $s$:\n",
    "\n",
    "$$\n",
    "t = diag(s) * diag(A)\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "73f4a284",
   "metadata": {},
   "outputs": [],
   "source": [
    "t = result.get_total_requirements()\n",
    "tech_values(t).head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "383f641d",
   "metadata": {},
   "source": [
    "### `/total-requirements-of/{tech-flow}`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "57a2c3a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "result.get_total_requirements_of(tech_flows[42])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8428b0b9",
   "metadata": {},
   "source": [
    "## Inventory results\n",
    "\n",
    "### `/total-flows`\n",
    "\n",
    "The total inventory result $g$ contains the total amounts of the intervention\n",
    "flows that cross the boundary with the environment. It can be calculated by\n",
    "summing up the scaled interventions of the processes in the system:\n",
    "\n",
    "$$\n",
    "g = B * s\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "70aedfe4",
   "metadata": {},
   "outputs": [],
   "source": [
    "g = result.get_total_flows()\n",
    "envi_values(g).head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "29ad968a",
   "metadata": {},
   "source": [
    "### `/total-flow-value-of/{envi-flow}`\n",
    "\n",
    "This method returns the total inventory result $g_i$ of a intervention flow $i$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf5fb295",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert g[42].amount == result.get_total_flow_value_of(g[42].envi_flow)\n",
    "result.get_total_flow_value_of(envi_flows[42])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f3235ec",
   "metadata": {},
   "source": [
    "### `/direct-flow-values-of/{envi-flow}`\n",
    "\n",
    "If we want to see the direct contributions of the processes in the system to the inventory result of a flow $i$, we can scale the row $i$ of the intervention matrix $B$ with the scaling vector $s$:\n",
    "\n",
    "$$\n",
    "g_i^t = B[i, :] * diag(s)\n",
    "$$\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ea6a59f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "i = envi_flows[42]\n",
    "unit = i.flow.ref_unit\n",
    "gi = result.get_direct_flow_values_of(i)\n",
    "plot = tech_values(gi, unit=lambda _: unit).plot(\n",
    "  y=\"Amount\", title=i.flow.name, ylabel=unit\n",
    ")\n",
    "glow()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d2f8141",
   "metadata": {},
   "source": [
    "### `/total-flow-values-of/{envi-flow}`\n",
    "\n",
    "This method returns the total result values of an intervention flow for the\n",
    "processes in a product system. Such a total result for a process $j$ ...\n",
    "\n",
    "$$\n",
    "M[i,:] * diagm(tf)\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a8cb08b7",
   "metadata": {},
   "outputs": [],
   "source": [
    "i = next(filter(lambda f: \"Carbon diox\" in f.flow.name, envi_flows))\n",
    "unit = i.flow.ref_unit\n",
    "vals = result.get_total_flow_values_of(i)\n",
    "tech_values(vals, unit=lambda _: unit, sort=\"asc\").plot(\n",
    "  y=\"Amount\", title=i.flow.name, ylabel=unit\n",
    ")\n",
    "glow()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4621b2f",
   "metadata": {},
   "source": [
    "### `/direct-flows-of/{tech-flow}`\n",
    "\n",
    "$$\n",
    "G[:,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cd9018da",
   "metadata": {},
   "outputs": [],
   "source": [
    "envi_values(result.get_direct_flows_of(tech_flows[1]), sort=\"desc\").head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f1576dc6",
   "metadata": {},
   "source": [
    "## `/direct-flow-of/{envi-flow}/{tech-flow}`\n",
    "\n",
    "$$\n",
    "G[i,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b2cd4389",
   "metadata": {},
   "outputs": [],
   "source": [
    "result.get_direct_flow_of(envi_flows[42], tech_flows[42])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d3a62f0",
   "metadata": {},
   "source": [
    "### `/total-flows-of-one/{tech-flow}`\n",
    "\n",
    "$$\n",
    "M[:,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd119588",
   "metadata": {},
   "outputs": [],
   "source": [
    "envi_values(result.get_total_flows_of_one(tech_flows[1])).head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ceceb2cd",
   "metadata": {},
   "source": [
    "### `/total-flow-of-one/{envi-flow}/{tech-flow}`\n",
    "\n",
    "$$\n",
    "M[i,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8718740a",
   "metadata": {},
   "outputs": [],
   "source": [
    "result.get_total_flow_of_one(envi_flows[42], tech_flows[42])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf2aefc5",
   "metadata": {},
   "source": [
    "### `/total-flows-of/{tech-flow}`\n",
    "\n",
    "$$\n",
    "tf[j] * M[:,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c6439809",
   "metadata": {},
   "outputs": [],
   "source": [
    "j = tech_flows[1]\n",
    "values = result.get_total_flows_of(j)\n",
    "envi_values(\n",
    "    list(filter(lambda i: i.envi_flow.flow.ref_unit == \"kg\", values))\n",
    ").plot(\n",
    "    y=\"Amount\",\n",
    "    ylabel=\"kg\",\n",
    "    title=f\"Total intervention mass flows of: {j.provider.name}\",\n",
    ")\n",
    "glow()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ad9f764",
   "metadata": {},
   "source": [
    "### `/total-flow-of/{envi-flow}/{tech-flow}`\n",
    "\n",
    "$$\n",
    "tf[j] * M[i,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f54fa884",
   "metadata": {},
   "outputs": [],
   "source": [
    "result.get_total_flow_of(envi_flows[42], tech_flows[42])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5618dc5d",
   "metadata": {},
   "source": [
    "### `/unscaled-flows-of/{tech-flow}`\n",
    "\n",
    "$$\n",
    "B[:,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e8242e90",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO does not exist yet\n",
    "envi_values(result.get_unscaled_flows_of(tech_flows[42])).head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7bab27b",
   "metadata": {},
   "source": [
    "## Impact assessment results\n",
    "\n",
    "### `/total-impacts`\n",
    "\n",
    "$$\n",
    "h = C * g\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75e207fb",
   "metadata": {},
   "outputs": [],
   "source": [
    "impact_values(result.get_total_impacts())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "24840956",
   "metadata": {},
   "source": [
    "### `/total-impact-value-of/{impact-category}`\n",
    "\n",
    "$$\n",
    "h[k]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "55650cb6",
   "metadata": {},
   "outputs": [],
   "source": [
    "result.get_total_impact_value_of(impact_categories[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b5cd592",
   "metadata": {},
   "source": [
    "### `/direct-impact-values-of/{impact-category}`\n",
    "\n",
    "$$\n",
    "H[k,:]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b05a878",
   "metadata": {},
   "outputs": [],
   "source": [
    "k = impact_categories[0]\n",
    "hk = result.get_direct_impact_values_of(k)\n",
    "tech_values(hk, unit=lambda _: k.ref_unit)[\"Amount\"].plot(\n",
    "    title=f\"Direct impacts of: {k.name}\", kind=\"hist\",bins=4\n",
    ")\n",
    "glow()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38afc388",
   "metadata": {},
   "source": [
    "### `/total-impact-values-of/{impact-category}`\n",
    "\n",
    "$$\n",
    "N[k,:] * diagm(tf)\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "672b246a",
   "metadata": {},
   "outputs": [],
   "source": [
    "df(result.get_total_impact_values_of(impact_categories[0]),\n",
    "  *tech_values(unit=lambda _: impact_categories[0].ref_unit)).head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea071590",
   "metadata": {},
   "source": [
    "### `/direct-impacts-of/{tech-flow}`\n",
    "\n",
    "$$\n",
    "H[:,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6e6ad88d",
   "metadata": {},
   "outputs": [],
   "source": [
    "df(result.get_direct_impacts_of(tech_flows[1]),\n",
    "  (\"Impact category\", lambda v: v.impact_category.name),\n",
    "  (\"Amount\", lambda v: v.amount),\n",
    "  (\"Unit\", lambda v: v.impact_category.ref_unit))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01356211",
   "metadata": {},
   "source": [
    "### `/direct-impact-of/{impact-category}/{tech-flow}`\n",
    "\n",
    "$$\n",
    "H[k,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b048a4e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "result.get_direct_impact_of(impact_categories[0], tech_flows[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb6e06fe",
   "metadata": {},
   "source": [
    "### `/total-impacts-of-one/{tech-flow}`\n",
    "\n",
    "$$\n",
    "N[:,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "488c8814",
   "metadata": {},
   "outputs": [],
   "source": [
    "df(result.get_total_impacts_of_one(tech_flows[1]),\n",
    "  (\"Impact category\", lambda v: v.impact_category.name),\n",
    "  (\"Amount\", lambda v: v.amount),\n",
    "  (\"Unit\", lambda v: v.impact_category.ref_unit))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b21a1471",
   "metadata": {},
   "source": [
    "### `/total-impact-of-one/{impact-category}/{tech-flow}`\n",
    "\n",
    "$$\n",
    "N[k,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a91aa247",
   "metadata": {},
   "outputs": [],
   "source": [
    "result.get_total_impact_of_one(impact_categories[0], tech_flows[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d303fce",
   "metadata": {},
   "source": [
    "### `/total-impacts-of/{tech-flow}`\n",
    "\n",
    "$$\n",
    "tf[j] * N[:,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0296c832",
   "metadata": {},
   "outputs": [],
   "source": [
    "df(result.get_total_impacts_of(tech_flows[1]),\n",
    "  (\"Impact category\", lambda v: v.impact_category.name),\n",
    "  (\"Amount\", lambda v: v.amount),\n",
    "  (\"Unit\", lambda v: v.impact_category.ref_unit))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "da66f3f5",
   "metadata": {},
   "source": [
    "### `/total-impact-of/{impact-category}/{tech-flow}`\n",
    "\n",
    "$$\n",
    "tf[j] * N[k,j]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "11fbecd9",
   "metadata": {},
   "outputs": [],
   "source": [
    "result.get_total_impact_of(impact_categories[0], tech_flows[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5832daaa",
   "metadata": {},
   "source": [
    "### `/impact-factors-of/{impact-category}`\n",
    "\n",
    "$$\n",
    "C[k,:]\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f1bef930",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "ipc-venv2",
   "language": "python",
   "name": "ipc-venv2"
  },
  "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.11.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
