Implement 221100 split#462
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
bl-young
left a comment
There was a problem hiding this comment.
Sharing some initial comments but given the complexity I will want to review more closely.
|
|
||
| # Anything still NaN (truly no parent, e.g. S00402) gets neutral 1.0 | ||
| ratio = ratio.fillna(1.0) | ||
| if cfg.implement_electricity_disaggregation: |
There was a problem hiding this comment.
I'm curious how this is handled for waste right now. Because waste sectors face the same issue right? I would think that the same approach would suffice here potentially? Does the map right above with _cornerstone_to_ceda_v7_parent() attempt to handle that?
There was a problem hiding this comment.
I'm not sure I fully understand the question.
If you are asking whether we can use the same mapping as for waste, I don't think so. The waste disagg is built into the cornerstone schema, whereas the electricity disagg is not. So we need additional mapping to expand the schema.
Does this answer the question?
| A: pd.DataFrame, original_year: int, target_year: int | ||
| ) -> pd.DataFrame: | ||
| price_ratio = get_cornerstone_industry_price_ratio(original_year, target_year) | ||
| price_ratio = price_ratio.reindex(A.index, fill_value=1.0) |
There was a problem hiding this comment.
this feels like it should already be done within get_cornerstone_industry_price_ratio so I'm not sure it needs to be done again
There was a problem hiding this comment.
Perhaps but this is the way it is structured in main. Should this be done in its own PR rather than here?
| implement_waste_disaggregation: bool = False # DRI: jorge.vendries | ||
| eeio_waste_disaggregation: ta.Optional[EEIOWasteDisaggConfig] = None | ||
| implement_electricity_reallocation: bool = False # DRI: jorge.vendries | ||
| implement_electricity_disaggregation: bool = False # DRI: jorge.vendries |
There was a problem hiding this comment.
This comment is relevant in a few places. Are we planning to evaluate the reallocation with and without disaggregation? I'm not sure what purpose that serves really. I would propose we just have a single flag and not over burden ourselves. (to be more clear, my suggestion would be to use implement_electricity_disaggregation and drop implement_electricity_reallocation
There was a problem hiding this comment.
Yes I agree the ultimate goal is to drop reallocation flag, but I do think it is worthwhile to evaluate reallocation in isolation. In other words, my intent was to keep them separate for now so we can better evaluate any source of variabity in disaggregated EFs. I.e., if the EFs change a lot, is that caused by the disaggregation itself, or the reallocation?
Does this make sense, or do you think this separation is unnecesary even for diagnostics?
There was a problem hiding this comment.
I would suggest keeping only implement_electricity_disaggregation
| assert config.implement_electricity_reallocation is True | ||
|
|
||
|
|
||
| def test_electricity_disaggregation_config_parsing() -> None: |
There was a problem hiding this comment.
I think this is duplicative of the validation in usa_config.py (though per my comment about the new flag this test might not be necessary at all)
| ELECTRICITY_AGGREGATE = "221100" | ||
| BALANCE_TOLERANCE = 1e6 | ||
| DISAGG_BALANCE_ATOL = 1.0 | ||
| IO_ACCOUNT_YEAR = 2017 |
There was a problem hiding this comment.
this should come from the model parameter inside the model config
| VA = derive_cornerstone_VA_after_waste() | ||
| if electricity_reallocation_enabled(): | ||
| V, Udom, Uimp, VA = reallocate_electricity_coproduction(V, Udom, Uimp, VA) | ||
| if electricity_disaggregation_enabled(): |
There was a problem hiding this comment.
I have this comment elsewhere as well but i think this double gating is unnecessary
| # `transform/output_data/` for 2019–2023. Load the cached parquet | ||
| # directly so the year-Y diagnostics get year-Y GHG data. | ||
| fbs = _load_cornerstone_ghg_fbs_from_gcs(usa.usa_ghg_data_year) | ||
| if usa.implement_electricity_disaggregation: |
There was a problem hiding this comment.
this implementation doesn't seem quite right. I think we should just be able to target the new method in _select_flowsa_ghg_method like other approaches. I think this particular if/else branch was intended for off years
93416b2 to
f31e667
Compare
309998f to
669acb4
Compare
…move unneeded files
669acb4 to
120547f
Compare
| fbs = _load_cornerstone_ghg_fbs_from_gcs(year) | ||
| if usa.new_ghg_method and usa.implement_electricity_disaggregation: | ||
| try: | ||
| from flowsa import getFlowBySector as get_flowsa_fbs # noqa: PLC0415 |
There was a problem hiding this comment.
flowsa is no longer a separate required package.
This method must depend on eGRID. Coding in a fallback to the GHGI is overcomplicated.
There was a problem hiding this comment.
There are correct references for getting an FBS elsewhere in this module.
getFlowBySector is already imported from
bedrock.transform.flowbysector
| ) | ||
|
|
||
|
|
||
| def _cornerstone_aq_matrix_set( |
There was a problem hiding this comment.
Why is this new internal function in here that is not specific to electricity disaggregation? Can it be avoided?
|
|
||
| if apply_inflation: | ||
| V = inflate_cornerstone_V_with_industry_pi(V, target_year=target_year) | ||
| validate_cornerstone(V, "V") |
There was a problem hiding this comment.
Why add this validation check to this PR?
| return _distribute_waste_parent_x_using_v_row_shares(x_cs) | ||
| x_cs.index.name = "sector" | ||
| x_out = _distribute_waste_parent_x_using_v_row_shares(x_cs) | ||
| validate_cornerstone(x_out, "X") |
There was a problem hiding this comment.
again this seems beyond the scope of this PR
| @@ -3,6 +3,12 @@ | |||
|
|
|||
| import pandas as pd | |||
There was a problem hiding this comment.
We should not be using this file any more for a main pipeline. I recommend moving all this code into usa_taxonomy_correspondence_helpers.py
| DISAGG_BALANCE_ATOL = 1.0 | ||
| IO_ACCOUNT_YEAR = 2017 | ||
|
|
||
| GENERATION_GO_SECTOR_NAMES: tuple[str, ...] = ( |
There was a problem hiding this comment.
These tuples defining names should be in taxonomy
| ) | ||
|
|
||
|
|
||
| def _diagonal_intersection_weights(w: pd.Series[float]) -> pd.DataFrame: |
There was a problem hiding this comment.
Unclear on what the w parameter is for..how do you prepare that. No documentation of that.
| ) | ||
|
|
||
|
|
||
| def build_electricity_disagg_weights(w: pd.Series[float]) -> DisaggWeights: |
There was a problem hiding this comment.
Unclear on what the w parameter is for..how do you prepare that. No documentation of that.
|
Code runs to generate model. Model is generated and |

cc:
Closes: cornerstone-data/methods#85
What changed? Why?
Implements monetary disaggregation of the aggregate
221100electricity sector into three sub-sectors —221110(generation),221121(transmission), and221122(distribution) — using gross-output shares derived from BEA UGO305-A data. This is the third major step in the electricity sector disaggregation pipeline, following the existing co-production reallocation work.The disaggregation runs in four sequential steps:
221100Make diagonal into a 3×3 diagonal block using GO weights221100Use self-use intersection diagonally221100industry column across sub-industries with fuel-commodity routing (generation-only fuels like coal, natural gas, petroleum go entirely to221110) and VA balancing to preserve row totals221100commodity row across all consuming industries using equal-price GO weightsA new
implement_electricity_disaggregationflag is added toUSAConfigwith a validator enforcing that bothimplement_waste_disaggregationandimplement_electricity_reallocationmust be enabled as prerequisites. When active, the schema expands from 405 to 407 sectors, and all Cornerstone matrix validations (V,U,A,B,X,Q) are routed through a new flag-awarevalidate_cornerstone()helper that replaces the previous static@pa.check_outputdecorators, allowing the same validation logic to work against either the 405- or 407-sector schema depending on config.Emissions attribution (
derive_E_usa) loads the eGRID-based FBS (GHG_national_Cornerstone_2023_egrid) when electricity disaggregation is enabled, with a fallback to the cached national FBS. SF6 emissions are routed to221121(transmission); all other gases go to221110(generation). Inflation helpers, the BEA summary-to-Cornerstone correspondence, and gross-outputxdistribution are all updated to propagate the parent221100values to the three sub-sectors.Two new config files are added: a test config (
test_usa_config_waste_disagg_electricity_disaggregation.yaml) and a full production config (2025_usa_cornerstone_full_model_electricity_disaggregation.yaml).Testing
New integration tests in
test_electricity_disaggregation.pycover:eeio_integration) confirming the 407-sector schema shape, absence of221100from all output matrices, Aq column sums ≤ 1, and non-zero emissions attribution to the disaggregated electricity columns