14
14
15
15
from genno .types import AnyQuantity
16
16
17
+ #: Expression for IAMC ‘variable’ names used in :func:`main`.
18
+ EXPR = r"^Emissions\|(?P<e>[^\|]+)\|Energy\|Demand\|Transportation(?:\|(?P<t>.*))?$"
19
+
17
20
18
21
def aviation_share (ref : "AnyQuantity" ) -> "AnyQuantity" :
19
22
"""Return (dummy) data for the share of aviation in emissions.
@@ -39,57 +42,6 @@ def aviation_share(ref: "AnyQuantity") -> "AnyQuantity":
39
42
)
40
43
41
44
42
- def finalize (
43
- q_all : "AnyQuantity" ,
44
- q_update : "AnyQuantity" ,
45
- model_name : str ,
46
- scenario_name : str ,
47
- path_out : "pathlib.Path" ,
48
- ) -> None :
49
- """Finalize output.
50
-
51
- 1. Reattach "Model" and "Scenario" labels.
52
- 2. Reassemble the "Variable" dimension/coords of `q_update`; drop "e" and "t".
53
- 3. Convert both `q_all` and `q_update` to :class:`pandas.Series`; update the former
54
- with the contents of the latter.
55
- 4. Adjust to IAMC ‘wide’ structure and write to `path_out`.
56
-
57
- Parameters
58
- ----------
59
- q_all :
60
- All data.
61
- q_update :
62
- Revised data to overwrite corresponding values in `q_all`.
63
- """
64
-
65
- def _expand (qty ):
66
- return qty .expand_dims (
67
- {"Model" : [model_name ], "Scenario" : [scenario_name ]}
68
- ).rename ({"n" : "Region" , "UNIT" : "Unit" , "VARIABLE" : "Variable" })
69
-
70
- s_all = q_all .pipe (_expand ).to_series ()
71
-
72
- s_all .update (
73
- q_update .pipe (_expand )
74
- .to_frame ()
75
- .reset_index ()
76
- .assign (
77
- Variable = lambda df : (
78
- "Emissions|" + df ["e" ] + "|Energy|Demand|Transportation|" + df ["t" ]
79
- ).str .replace ("|_T" , "" )
80
- )
81
- .drop (["e" , "t" ], axis = 1 )
82
- .set_index (s_all .index .names )[0 ]
83
- )
84
-
85
- (
86
- s_all .unstack ("y" )
87
- .reorder_levels (["Model" , "Scenario" , "Region" , "Variable" , "Unit" ])
88
- .reset_index ()
89
- .to_csv (path_out , index = False )
90
- )
91
-
92
-
93
45
def extract_dims (
94
46
qty : "AnyQuantity" , dim_expr : dict , * , drop : bool = True , fillna : str = "_T"
95
47
) -> "AnyQuantity" :
@@ -145,56 +97,81 @@ def extract_dims1(qty: "AnyQuantity", dim: dict) -> "AnyQuantity": # pragma: no
145
97
return result
146
98
147
99
148
- def select_re ( qty : "AnyQuantity" , indexers : dict ) -> "AnyQuantity" :
149
- """Select using regular expressions for each dimension."""
150
- new_indexers = dict ()
151
- for dim , expr in indexers . items ():
152
- new_indexers [ dim ] = list (
153
- map ( str , filter ( re . compile ( expr ). match , qty . coords [ dim ]. data . astype ( str )))
154
- )
155
- return qty . sel ( new_indexers )
100
+ def finalize (
101
+ q_all : "AnyQuantity" ,
102
+ q_update : "AnyQuantity" ,
103
+ model_name : str ,
104
+ scenario_name : str ,
105
+ path_out : "pathlib.Path" ,
106
+ ) -> None :
107
+ """Finalize output.
156
108
109
+ 1. Reattach "Model" and "Scenario" labels.
110
+ 2. Reassemble the "Variable" dimension/coords of `q_update`; drop "e" and "t".
111
+ 3. Convert both `q_all` and `q_update` to :class:`pandas.Series`; update the former
112
+ with the contents of the latter.
113
+ 4. Adjust to IAMC ‘wide’ structure and write to `path_out`.
157
114
158
- #: Expression for IAMC ‘variable’ names used in :func:`main`.
159
- EXPR = r"^Emissions\|(?P<e>[^\|]+)\|Energy\|Demand\|Transportation(?:\|(?P<t>.*))?$"
115
+ Parameters
116
+ ----------
117
+ q_all :
118
+ All data.
119
+ q_update :
120
+ Revised data to overwrite corresponding values in `q_all`.
121
+ """
122
+
123
+ def _expand (qty ):
124
+ return qty .expand_dims (
125
+ {"Model" : [model_name ], "Scenario" : [scenario_name ]}
126
+ ).rename ({"n" : "Region" , "UNIT" : "Unit" , "VARIABLE" : "Variable" })
127
+
128
+ s_all = q_all .pipe (_expand ).to_series ()
129
+
130
+ s_all .update (
131
+ q_update .pipe (_expand )
132
+ .to_frame ()
133
+ .reset_index ()
134
+ .assign (
135
+ Variable = lambda df : (
136
+ "Emissions|" + df ["e" ] + "|Energy|Demand|Transportation|" + df ["t" ]
137
+ ).str .replace ("|_T" , "" )
138
+ )
139
+ .drop (["e" , "t" ], axis = 1 )
140
+ .set_index (s_all .index .names )[0 ]
141
+ )
142
+
143
+ (
144
+ s_all .unstack ("y" )
145
+ .reorder_levels (["Model" , "Scenario" , "Region" , "Variable" , "Unit" ])
146
+ .reset_index ()
147
+ .to_csv (path_out , index = False )
148
+ )
160
149
161
150
162
151
@minimum_version ("genno 1.25" )
163
- def main (path_in : "pathlib.Path" , path_out : "pathlib.Path" ) :
152
+ def main (path_in : "pathlib.Path" , path_out : "pathlib.Path" , method : str ) -> None :
164
153
"""Postprocess aviation emissions for SSP 2024.
165
154
166
155
1. Read input data from `path_in`.
167
- 2. Select data with variable names matching :data:`EXPR`.
168
- 3. Calculate (identical) values for:
169
-
170
- - ``Emissions|*|Energy|Demand|Transportation|Aviation``
171
- - ``Emissions|*|Energy|Demand|Transportation|Aviation|International``
172
-
173
- These are currently calculated as the product of :func:`aviation_share` and
174
- ``Emissions|*|Energy|Demand|Transportation``.
175
- 4. Subtract (3) from:
176
- ``Emissions|*|Energy|Demand|Transportation|Road Rail and Domestic Shipping``
177
- 5. Recombine with all other, unmodified data.
178
- 6. Write to `path_out`.
156
+ 2. Call either :func:`prepare_method_A` or :func:`prepare_method_B` according to
157
+ the value of `method`.
158
+ 3. Write to `path_out`.
179
159
180
160
Parameters
181
161
----------
182
162
path_in :
183
163
Input data path.
184
164
path_out :
185
165
Output data path.
166
+ method :
167
+ either 'A' or 'B'.
186
168
"""
187
169
import pandas as pd
188
170
189
- # Shorthand
190
- e_t = ("e" , "t" )
191
- t = "t"
192
- k_input = genno .Key ("input" , ("n" , "y" , "VARIABLE" , "UNIT" ))
193
- k = genno .KeySeq ("result" , ("n" , "y" , "UNIT" ) + e_t )
194
-
195
171
c = genno .Computer ()
196
172
197
173
# Read the data from `path`
174
+ k_input = genno .Key ("input" , ("n" , "y" , "VARIABLE" , "UNIT" ))
198
175
c .add (
199
176
k_input ,
200
177
iamc_like_data_for_query ,
@@ -207,6 +184,38 @@ def main(path_in: "pathlib.Path", path_out: "pathlib.Path"):
207
184
df = pd .read_csv (path_in , nrows = 1 )
208
185
c .add ("model name" , genno .quote (df ["Model" ].iloc [0 ]))
209
186
c .add ("scenario name" , genno .quote (df ["Scenario" ].iloc [0 ]))
187
+ c .add ("path out" , path_out )
188
+
189
+ # Call a function to prepare the remaining calculations
190
+ prepare_func = {
191
+ "A" : prepare_method_A ,
192
+ "B" : prepare_method_B ,
193
+ }[method ]
194
+ prepare_func (c , k_input )
195
+
196
+ # Execute
197
+ c .get ("target" )
198
+
199
+
200
+ def prepare_method_A (c : "genno.Computer" , k_input : "genno.Key" ) -> None :
201
+ """Prepare calculations using method 'A'.
202
+
203
+ 1. Select data with variable names matching :data:`EXPR`.
204
+ 2. Calculate (identical) values for:
205
+
206
+ - ``Emissions|*|Energy|Demand|Transportation|Aviation``
207
+ - ``Emissions|*|Energy|Demand|Transportation|Aviation|International``
208
+
209
+ These are currently calculated as the product of :func:`aviation_share` and
210
+ ``Emissions|*|Energy|Demand|Transportation``.
211
+ 3. Subtract (2) from:
212
+ ``Emissions|*|Energy|Demand|Transportation|Road Rail and Domestic Shipping``
213
+ 4. Recombine with all other, unmodified data.
214
+ """
215
+ # Shorthand
216
+ e_t = ("e" , "t" )
217
+ t = "t"
218
+ k = genno .KeySeq ("result" , ("n" , "y" , "UNIT" ) + e_t )
210
219
211
220
# Filter on "VARIABLE"
212
221
c .add (k [0 ] / e_t , select_re , k_input , indexers = {"VARIABLE" : EXPR })
@@ -256,8 +265,20 @@ def main(path_in: "pathlib.Path", path_out: "pathlib.Path"):
256
265
k [5 ],
257
266
"model name" ,
258
267
"scenario name" ,
259
- path_out = path_out ,
268
+ "path out" ,
260
269
)
261
270
262
- # Execute
263
- c .get ("target" )
271
+
272
+ def prepare_method_B (c , k_input : "genno.Key" ):
273
+ """Prepare calculations using method 'B'."""
274
+ raise NotImplementedError
275
+
276
+
277
+ def select_re (qty : "AnyQuantity" , indexers : dict ) -> "AnyQuantity" :
278
+ """Select from `qty` using regular expressions for each dimension."""
279
+ new_indexers = dict ()
280
+ for dim , expr in indexers .items ():
281
+ new_indexers [dim ] = list (
282
+ map (str , filter (re .compile (expr ).match , qty .coords [dim ].data .astype (str )))
283
+ )
284
+ return qty .sel (new_indexers )
0 commit comments