Skip to content

feat: implement B3 indicators calculations to CBA#350

Merged
measrainsey merged 31 commits intomasterfrom
feat/b3-indicator
Jan 27, 2026
Merged

feat: implement B3 indicators calculations to CBA#350
measrainsey merged 31 commits intomasterfrom
feat/b3-indicator

Conversation

@measrainsey
Copy link
Copy Markdown
Member

@measrainsey measrainsey commented Dec 23, 2025

Closes:

Changes proposed in this Pull Request

This PR adds the calculation of the B3 indicator for the Cost-Benefit Analysis (CBA) workflow.

Workflow

The only changes made to the workflow are in the scripts/cba/make_indicators.py file:

  • The calculate_b3_indicator() function has been added to calculate the B3 indicators, as well as some helper functions for getting information about networks using the PyPSA statistics module
  • The B3 indicator(s) are then added to the indicators CSV

The resulting columns that are added to the indicators CSV are:

  • B3_res_capacity_change_mw: difference in RES capacity (MW) with and without the project
  • B3_res_generation_change_mwh: difference in RES generation (MWh) with and without the project
  • B3_res_dump_change_mwh: difference in RES curtailment (MWh) with and without the project

Open issues

RES benefit calculation

One thing I am not sure yet is how to implement this part of the text here from the CBA Implementation Guideline (p. 69):

Screenshot 2025-12-23 at 3 57 36 PM

If E_project is the generation of JUST the project (and not generation from all RES technologies in the whole network), then we would need to find a way to pull out the specific project from the network and get its generation?

Notes

Checklist

  • I tested my contribution locally and it works as intended.
  • Code and workflow changes are sufficiently documented.
  • [ ] Changed dependencies are added to pixi.toml (using pixi add <dependency-name>).
  • [ ] Changes in configuration options are added in config/config.default.yaml.
  • Changes in configuration options are documented in doc/configtables/*.csv.
  • Changes in configuration options are added in config/test/*.yaml.
  • [ ] Open-TYNDP SPDX license header added to all touched files.
  • [ ] Sources of newly added data are documented in doc/data_sources.rst.
  • [ ] New rules are documented in the appropriate doc/*.rst files.
  • A release note doc/release_notes.rst is added.
  • Major features are documented with up-to-date information in README and doc/index.rst.
  • [ ] Module docstrings added to new Python scripts.

@measrainsey measrainsey linked an issue Dec 23, 2025 that may be closed by this pull request
3 tasks
@measrainsey measrainsey changed the title feat: add calculation for B3 indicators feat: implement B3 indicator calculation to CBA Dec 23, 2025
@measrainsey measrainsey changed the title feat: implement B3 indicator calculation to CBA feat: implement B3 indicators calculations to CBA Dec 23, 2025
@measrainsey measrainsey self-assigned this Dec 23, 2025
@measrainsey measrainsey marked this pull request as ready for review December 23, 2025 15:13
Copy link
Copy Markdown
Collaborator

@lisazeyen lisazeyen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, thanks @measrainsey! Looks good. The only remaining thing which needs to be changed is setting whenever you call the statistics module nice_names=False and take the same list for renewable carriers which is already part of the config.

Question to @cdgaete : do you know if for some projects additional renewable capacities are given, which are getting connected by the new project, e.g. a transmission line connecting to a offshore hub?

Comment thread config/config.tyndp.yaml Outdated
central: 628
high: 662
res_carriers:
- Onshore Wind
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a mix of some carriers renamed to there "nice names" and some technologies still having the pypsa network names. I would suggest when calling the statistic module to set nice_names=False so that there is no renaming of carriers. This would require some renaming in this list, e.g. Onshore Wind -> onwind. You can directly use the electricity.tyndp_renewable_carriers option then

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use nice_names=False in n.statistics() - and also removed the need for the cba.res_carriers in the config, instead now using electricity.tyndp_renewable_carriers

return CO2_emissions_per_carrier


def calculate_res_capacity_per_carrier(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just as a note: We are currently fixing the capacities so there will be never a difference in installed capacity per carrier. I think this is mainly for projects which are e.g. connecting offshore wind parks. But I am not sure if that value of additional connected capacity is given somewhere.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying! Then I guess this explains why the capacity differences in my quick checks have been 0 so far :)

@measrainsey measrainsey requested a review from lisazeyen January 14, 2026 09:55
@measrainsey
Copy link
Copy Markdown
Member Author

Thanks @lisazeyen for your review! I hope I addressed your comments correctly, let me know if not

@cdgaete also let me know if you have any feedback regarding the capacities stuff

Comment thread scripts/cba/make_indicators.py Outdated
Copy link
Copy Markdown
Collaborator

@lisazeyen lisazeyen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just one small comment concerning the naming, the rest looks good!

measrainsey and others added 7 commits January 14, 2026 15:53
 Conflicts:
	config/test/config.tyndp.yaml
	doc/release_notes.rst
	envs/default_linux-64.pin.txt
	envs/default_osx-64.pin.txt
	envs/default_osx-arm64.pin.txt
	envs/default_win-64.pin.txt
	pixi.lock
 Conflicts:
	config/test/config.tyndp.yaml
	doc/release_notes.rst
	envs/default_linux-64.pin.txt
	envs/default_osx-64.pin.txt
	envs/default_osx-arm64.pin.txt
	envs/default_win-64.pin.txt
	pixi.lock
Base automatically changed from feat/b2-indicator to master January 23, 2026 12:16
@lisazeyen lisazeyen removed the request for review from cdgaete January 26, 2026 13:24
@measrainsey
Copy link
Copy Markdown
Member Author

Noting here that the CI is failing in the SB test phase (pixi run -e open-tyndp tyndp-sb-test):

localrule retrieve_eu_nuts_2021:
    input: https://zenodo.org/records/15846440/files/ref-nuts-2021-01m.geojson.zip (retrieve from storage)
    output: data/eu_nuts2021/archive/2021-01-01/ref-nuts-2021-01m.geojson.zip, data/eu_nuts2021/archive/2021-01-01/ref-nuts-2021-01m.geojson, data/eu_nuts2021/archive/2021-01-01/ref-nuts-2021-01m.geojson/NUTS_RG_01M_2021_4326_LEVL_3.geojson, data/eu_nuts2021/archive/2021-01-01/ref-nuts-2021-01m.geojson/NUTS_RG_01M_2021_4326_LEVL_2.geojson, data/eu_nuts2021/archive/2021-01-01/ref-nuts-2021-01m.geojson/NUTS_RG_01M_2021_4326_LEVL_1.geojson, data/eu_nuts2021/archive/2021-01-01/ref-nuts-2021-01m.geojson/NUTS_RG_01M_2021_4326_LEVL_0.geojson
    jobid: 16
    reason: Missing output files: data/eu_nuts2021/archive/2021-01-01/ref-nuts-2021-01m.geojson/NUTS_RG_01M_2021_4326_LEVL_3.geojson
    resources: tmpdir=/tmp
Removing local copy of storage file: https://zenodo.org/records/4767098/files/IGGIELGN.zip (in storage)
[Mon Jan 26 08:29:00 2026]
Finished jobid: 42 (Rule: retrieve_gas_infrastructure_data)
47 of 218 steps (22%) done
[Mon Jan 26 08:29:00 2026]
Finished jobid: 107 (Rule: retrieve_cost_data)
48 of 218 steps (22%) done
[Mon Jan 26 08:29:00 2026]
Finished jobid: 51 (Rule: retrieve_powerplants)
49 of 218 steps (22%) done
Select jobs to execute...
Execute 3 jobs...
Retrieving from storage: https://zenodo.org/records/16355917/files/World_EEZ_v12_20231025_LR.zip
Retrieving from storage: https://zenodo.org/records/16992755/files/osm_boundaries.zip
WorkflowError while get'ing https://zenodo.org/api/records/16992755
Failed to fetch Zenodo record metadata: HTTP 503 (https://zenodo.org/api/records/16992755), attempt 1/5 failed - retrying in 3 seconds...
WorkflowError while get'ing https://zenodo.org/api/records/16992755
Failed to fetch Zenodo record metadata: HTTP 504 (https://zenodo.org/api/records/16992755), attempt 2/5 failed - retrying in 6 seconds...
WorkflowError while get'ing https://zenodo.org/records/16355917/files/World_EEZ_v12_20231025_LR.zip
Failed to download from Zenodo: HTTP 504 (https://zenodo.org/records/16355917/files/World_EEZ_v12_20231025_LR.zip), attempt 1/5 failed - retrying in 3 seconds...
Finished retrieval.
WorkflowError while get'ing https://zenodo.org/api/records/16355917
Failed to fetch Zenodo record metadata: HTTP 504 (https://zenodo.org/api/records/16355917), attempt 1/5 failed - retrying in 3 seconds...
File World_EEZ_v12_20231025_LR.zip not found in Zenodo record 16355917, attempt 2/5 failed - retrying in 6 seconds...
File World_EEZ_v12_20231025_LR.zip not found in Zenodo record 16355917, attempt 3/5 failed - retrying in 12 seconds...
WorkflowError while get'ing https://zenodo.org/records/16355917/files/World_EEZ_v12_20231025_LR.zip
Failed to download from Zenodo: HTTP 504 (https://zenodo.org/records/16355917/files/World_EEZ_v12_20231025_LR.zip), attempt 4/5 failed - retrying in 24 seconds...
File World_EEZ_v12_20231025_LR.zip not found in Zenodo record 16355917, attempt 5/5 failed - giving up!
WorkflowError:
Failed to retrieve input from storage.
WorkflowError:
    File World_EEZ_v12_20231025_LR.zip not found in Zenodo record 16355917

However, running pixi run -e open-tyndp tyndp-cba-test locally finishes without error.

@measrainsey measrainsey merged commit 0960d9e into master Jan 27, 2026
4 of 6 checks passed
@measrainsey measrainsey deleted the feat/b3-indicator branch January 27, 2026 12:02
@measrainsey measrainsey added the CBA Cost Benefit Analysis label Feb 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CBA Cost Benefit Analysis

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[SUB] Add B3 indicator

4 participants