44import pandas as pd
55
66if TYPE_CHECKING :
7+ from ixmp4 import Run
8+ from ixmp4 .core import IndexSet , Parameter , Table
9+
710 from message_ix .core import Scenario
811
912from ixmp import Platform
10- from ixmp4 import Run
11- from ixmp4 . core import IndexSet , Parameter , Table
13+
14+ from message_ix . util . ixmp4 import on_ixmp4backend
1215
1316from .scenario_data import (
1417 DEFAULT_INDEXSET_DATA ,
2831
2932# (According to ixmp_source.)
3033# """
31- # # NOTE this assumes an IXMP4Backend
34+ # if not on_ixmp4backend(scenario):
35+ # return
36+ #
3237# # Get the Run associated with the Scenario
33- # run = cast(Run, scenario.platform._backend.index[scenario])
38+ # run = cast(" Run" , scenario.platform._backend.index[scenario])
3439
3540# # Add all required IndexSets
3641# for indexset_name in REQUIRED_INDEXSETS:
7176
7277def add_default_data (scenario : "Scenario" ) -> None :
7378 """Add default data expected in a MESSAGEix Scenario."""
74- # NOTE this assumes an IXMP4Backend
79+ if not on_ixmp4backend (scenario ):
80+ return
81+
7582 # Get the Run associated with the Scenario
76- run = cast (Run , scenario .platform ._backend .index [scenario ])
83+ run = cast (" Run" , scenario .platform ._backend .index [scenario ])
7784
7885 # Add IndexSet data
7986 for indexset_data_info in DEFAULT_INDEXSET_DATA :
@@ -121,11 +128,13 @@ def ensure_required_indexsets_have_data(scenario: "Scenario") -> None:
121128 ValueError
122129 If the required IndexSets are empty.
123130 """
131+ if not on_ixmp4backend (scenario ):
132+ return
133+
124134 indexsets_to_check = ("node" , "technology" , "year" , "time" )
125135
126- # NOTE this assumes an IXMP4Backend
127136 # Get the Run associated with the Scenario
128- run = cast (Run , scenario .platform ._backend .index [scenario ])
137+ run = cast (" Run" , scenario .platform ._backend .index [scenario ])
129138
130139 # Raise an error if any of the checked IndexSets are empty
131140 for name in indexsets_to_check :
@@ -136,7 +145,7 @@ def ensure_required_indexsets_have_data(scenario: "Scenario") -> None:
136145
137146
138147def _maybe_add_to_table (
139- table : Table , data : Union [dict [str , Any ], pd .DataFrame ]
148+ table : " Table" , data : Union [dict [str , Any ], pd .DataFrame ]
140149) -> None :
141150 """Add (parts of) `data` to `table` if they are missing."""
142151 # NOTE This function doesn't handle empty data as internally, this won't happen
@@ -166,9 +175,11 @@ def compose_dimension_map(
166175 dimension: 'node' or 'time'
167176 Whether to handle the spatial or temporal dimension.
168177 """
169- # NOTE this assumes an IXMP4Backend
178+ if not on_ixmp4backend (scenario ):
179+ return
180+
170181 # Get the Run associated with the Scenario
171- run = cast (Run , scenario .platform ._backend .index [scenario ])
182+ run = cast (" Run" , scenario .platform ._backend .index [scenario ])
172183
173184 # Handle both spatial and temporal dimensions
174185 name_part = "spatial" if dimension == "node" else "temporal"
@@ -236,15 +247,15 @@ def _find_all_descendants(parent: T) -> list[T]:
236247
237248
238249def _maybe_add_single_item_to_indexset (
239- indexset : IndexSet , data : Union [float , int , str ]
250+ indexset : " IndexSet" , data : Union [float , int , str ]
240251) -> None :
241252 """Add `data` to `indexset` if it is missing."""
242253 if data not in list (indexset .data ):
243254 indexset .add (data = data )
244255
245256
246257def _maybe_add_list_to_indexset (
247- indexset : IndexSet , data : Union [list [float ], list [int ], list [str ]]
258+ indexset : " IndexSet" , data : Union [list [float ], list [int ], list [str ]]
248259) -> None :
249260 """Add missing parts of `data` to `indexset`."""
250261 # NOTE missing will always only have one type, but how to tell mypy?
@@ -255,7 +266,8 @@ def _maybe_add_list_to_indexset(
255266
256267
257268def _maybe_add_to_indexset (
258- indexset : IndexSet , data : Union [float , int , str , list [float ], list [int ], list [str ]]
269+ indexset : "IndexSet" ,
270+ data : Union [float , int , str , list [float ], list [int ], list [str ]],
259271) -> None :
260272 """Add (parts of) `data` to `indexset` if they are missing."""
261273 # NOTE This function doesn't handle empty data as internally, this won't happen
@@ -268,7 +280,7 @@ def _maybe_add_to_indexset(
268280# NOTE this could be combined with `_maybe_add_to_table()`, but that function would be
269281# slower than necessary (though likely not by much). Is the maintenance effort worth it?
270282def _maybe_add_to_parameter (
271- parameter : Parameter , data : Union [dict [str , Any ], pd .DataFrame ]
283+ parameter : " Parameter" , data : Union [dict [str , Any ], pd .DataFrame ]
272284) -> None :
273285 """Add (parts of) `data` to `parameter` if they are missing."""
274286 # NOTE This function doesn't handle empty data as internally, this won't happen
@@ -291,14 +303,33 @@ def _maybe_add_to_parameter(
291303 parameter .add (data = new_data )
292304
293305
306+ def compose_maps (scenario : "Scenario" ) -> None :
307+ """Compose maps.
308+
309+ - Call :func:`compose_dimension_map` for:
310+
311+ - :py:`dimension="node"`
312+ - :py:`dimension="time"`
313+
314+ - Call :func:`compose_period_map`.
315+ """
316+ # Compose some auxiliary tables
317+ for dimension in ("node" , "time" ):
318+ compose_dimension_map (scenario = scenario , dimension = dimension )
319+
320+ compose_period_map (scenario = scenario )
321+
322+
294323def compose_period_map (scenario : "Scenario" ) -> None :
295324 """Add data to the 'duration_period' Parameter in `scenario`.
296325
297326 This covers `assignPeriodMaps()` from ixmp_source.
298327 """
299- # NOTE this assumes an IXMP4Backend
328+ if not on_ixmp4backend (scenario ):
329+ return
330+
300331 # Get the Run associated with the Scenario
301- run = cast (Run , scenario .platform ._backend .index [scenario ])
332+ run = cast (" Run" , scenario .platform ._backend .index [scenario ])
302333
303334 # TODO Included here in ixmp_source; this should likely move to add_default_data
304335 # Add one default item to 'type_year'
0 commit comments