-
Notifications
You must be signed in to change notification settings - Fork 157
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Add 'sankey' optional dependencies set. - Reporter.add_sankey() - Sort methods in alpha order. - Include all steps for figure generation. - Expand docstring. - .tools.sankey —rename from .util.sankey - Sort methods in order. - Simplify type hints. - Remove year= parameter from map_for_sankey() - Add warning if map_for_sankey() gives an empty result. - Reorganize tutorial to align with simplified interface. - Simplify tests - Update docs - Add doc/tools/sankey.rst - Add plotly to intersphinx config. - Remove trailing whitespace in tutorial/README.rst - Link docs, tutorial in release notes.
- Loading branch information
Showing
12 changed files
with
346 additions
and
215 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
.. currentmodule:: message_ix.tools.sankey | ||
|
||
:mod:`.sankey`: generate Sankey diagrams | ||
**************************************** | ||
|
||
See :meth:`.Reporter.add_sankey` and the :file:`westeros_sankey.ipynb` :ref:`tutorial <tutorial-westeros>`. | ||
|
||
API reference | ||
============= | ||
|
||
.. automodule:: message_ix.tools.sankey | ||
:members: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from message_ix.report import Reporter | ||
from message_ix.testing import make_westeros | ||
from message_ix.tools.sankey import map_for_sankey | ||
|
||
|
||
def test_map_for_sankey(test_mp, request): | ||
from genno.operator import concat | ||
|
||
scen = make_westeros(test_mp, solve=True, request=request) | ||
rep = Reporter.from_scenario(scen, units={"replace": {"-": ""}}) | ||
df = concat(rep.get("in::pyam"), rep.get("out::pyam")).filter(year=700) | ||
|
||
# Set expectations | ||
expected_all = { | ||
"in|final|electricity|bulb|standard": ("final|electricity", "bulb|standard"), | ||
"in|secondary|electricity|grid|standard": ( | ||
"secondary|electricity", | ||
"grid|standard", | ||
), | ||
"out|final|electricity|grid|standard": ("grid|standard", "final|electricity"), | ||
"out|secondary|electricity|coal_ppl|standard": ( | ||
"coal_ppl|standard", | ||
"secondary|electricity", | ||
), | ||
"out|secondary|electricity|wind_ppl|standard": ( | ||
"wind_ppl|standard", | ||
"secondary|electricity", | ||
), | ||
"out|useful|light|bulb|standard": ("bulb|standard", "useful|light"), | ||
} | ||
|
||
# Load all variables | ||
assert expected_all == map_for_sankey(df, node="Westeros") | ||
|
||
x = "final|electricity" | ||
assert {k: v for (k, v) in expected_all.items() if x not in v} == map_for_sankey( | ||
df, node="Westeros", exclude=[x] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import logging | ||
from typing import TYPE_CHECKING | ||
|
||
try: | ||
from pyam.str import get_variable_components | ||
except ImportError: # Python < 3.10 → pyam-iamc < 3 | ||
from pyam.utils import get_variable_components | ||
|
||
|
||
if TYPE_CHECKING: | ||
import pyam | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
def exclude_flow(flow: tuple[str, str], exclude: list[str]) -> bool: | ||
"""Return :any:`True` if either the source or target of `flow` is in `exclude`.""" | ||
return flow[0] in exclude or flow[1] in exclude | ||
|
||
|
||
def get_source_and_target(variable: str) -> tuple[str, str]: | ||
"""Get source and target for the `variable` flow.""" | ||
start_idx, end_idx = get_start_and_end_index(variable) | ||
return ( | ||
get_variable_components(variable, start_idx, join=True), | ||
get_variable_components(variable, end_idx, join=True), | ||
) | ||
|
||
|
||
def get_start_and_end_index(variable: str) -> tuple[list[int], list[int]]: | ||
"""Get indices of source and target in variable name.""" | ||
return ( | ||
([1, 2], [3, 4]) | ||
if get_variable_components(variable, 0) == "in" | ||
else ([3, 4], [1, 2]) | ||
) | ||
|
||
|
||
def map_for_sankey( | ||
iam_df: "pyam.IamDataFrame", node: str, exclude: list[str] = [] | ||
) -> dict[str, tuple[str, str]]: | ||
"""Maps input to output flows to enable Sankey diagram. | ||
Parameters | ||
---------- | ||
iam_df : :class:`pyam.IamDataframe` | ||
Data to plot as Sankey diagram. | ||
node : str | ||
The node (MESSAGEix) or region (pyam) to plot. | ||
exclude : list[str], optional | ||
Flows to omit from the diagram. By default, nothing is excluded. | ||
Returns | ||
------- | ||
dict | ||
mapping from variable names to 2-tuples of their (inputs, output) flows. | ||
""" | ||
result = { | ||
var: get_source_and_target(var) | ||
for var in iam_df.filter(region=node + "*").variable | ||
if not exclude_flow(get_source_and_target(var), exclude) | ||
} | ||
|
||
if not result: | ||
log.warning( | ||
f"No mapping entries generated for {node=}, {exclude=} and data:\n" | ||
+ repr(iam_df) | ||
) | ||
|
||
return result | ||
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.