75 notebooks#84
Conversation
|
The latest MUSE2 release uses the old file structure, so those tests are failing - but it is for a known reason. |
dc2917
left a comment
There was a problem hiding this comment.
Seems reasonable to me!
is far from ideal from the processing perspective. Performance-wise, there are vectorised options that are faster than apply, but this one was more readable.
I think for a notebook this sounds like a good approach.
|
This is the vectorised version, by the way: # Try merging on asset_id first, then fall back to group_id for unmatched rows
merged = asset_capacities.merge(
assets[["asset_id", "agent_id", "process_id", "commission_year"]],
on="asset_id",
how="left"
)
# Fill in rows where asset_id was None using group_id
mask = merged["agent_id"].isna()
fallback = asset_capacities[mask].merge(
assets[["group_id", "agent_id", "process_id", "commission_year"]],
on="group_id",
how="left"
)
merged.loc[mask, ["agent_id", "process_id", "commission_year"]] = fallback[["agent_id", "process_id", "commission_year"]].values
asset_capacities = merged |
Yeah, it's not that it's unclear, but it does make the process look more cumbersome, even if it's less work for the computer to do. I guess it depends on the purpose of the notebook? |
There was a problem hiding this comment.
This isn't quite right I'm afraid. asset_capacities.csv has a row for each asset in each year that it has capacity, so it's just a matter of merging this table with assets.csv to add metadata, then grouping by (milestone_year, agent_id, process_id) and summing. With some pandas trickery this can be relatively concise:
assets = pd.read_csv(OUTPUT_DIR / "assets.csv")
asset_capacities = pd.read_csv(OUTPUT_DIR / "asset_capacities.csv")
merged = asset_capacities.merge(assets, on=["asset_id", "group_id"])
agg_capacities = merged.groupby(["milestone_year", "agent_id", "process_id"])[
"capacity"
].sum()
agg_capacities_wide = agg_capacities.unstack(["agent_id", "process_id"], fill_value=0)
agents = agg_capacities_wide.columns.get_level_values("agent_id").unique()
fig, axes = plt.subplots(1, len(agents), figsize=(4 * len(agents), 4))
for ax, agent in zip(axes, agents):
agg_capacities_wide[agent].plot(
kind="bar", stacked=True, ax=ax, title=agent, xlabel="Year", ylabel="Capacity"
)
plt.tight_layout()I think stacked bars look better as well
If we wanted to use something like seaborn I think this could be even more concise (e.g. no need to loop over agents)
There was a problem hiding this comment.
We now copy the input data to the output folder (EnergySystemsModellingLab/MUSE2#1282), so we can drop this.
I don't think we need to read model.toml anyway
There was a problem hiding this comment.
Should remove this comment as it isn't true
There was a problem hiding this comment.
Pull request overview
Updates the example analysis notebooks to align with the new MUSE2 output file structure (splitting time-varying capacities into asset_capacities.csv and keeping metadata in assets.csv), and improves plot layout/legibility.
Changes:
- Refactors the capacity notebook to compute invested capacity from
asset_capacities.csvmerged with metadata fromassets.csv. - Adjusts plot layouts (legend placement in
prices.ipynb, stacked bar plots incapacity.ipynb). - Updates notebook metadata (kernel display name / Python version).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| notebooks/prices.ipynb | Improves legend placement for the price bar plot and updates notebook metadata. |
| notebooks/capacity.ipynb | Reworks capacity aggregation to use asset_capacities.csv + assets.csv, and updates plotting logic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "merged = asset_capacities.merge(assets, on=[\"asset_id\", \"group_id\"])\n", | ||
| "agg_capacities = merged.groupby([\"milestone_year\", \"agent_id\", \"process_id\"])[\n", | ||
| " \"capacity\"\n", | ||
| "].sum()\n", | ||
| "agg_capacities_wide = agg_capacities.unstack([\"agent_id\", \"process_id\"], fill_value=0)\n", |
There was a problem hiding this comment.
It might work in this case because there's no group_id in any of the rows. Maybe if there were, things would fail.
There was a problem hiding this comment.
I tried it with the simple_divisible model (which has rows with group_id populated) and it worked, so I think it's fine
| "agents = agg_capacities_wide.columns.get_level_values(\"agent_id\").unique()\n", | ||
| "fig, axes = plt.subplots(1, len(agents), figsize=(4 * len(agents), 4))\n", | ||
| "for ax, agent in zip(axes, agents):\n", | ||
| " capacity[capacity[\"agent_id\"] == agent].pivot(\n", | ||
| " index=\"year\", columns=\"process_id\", values=\"capacity\"\n", | ||
| " ).plot(kind=\"bar\", ax=ax)\n", | ||
| " ax.set_title(agent)\n", | ||
| " ax.set_xlabel(\"Year\")\n", | ||
| " ax.set_ylabel(\"Capacity\")\n", | ||
| " ax.legend(title=\"Process\")" | ||
| " agg_capacities_wide[agent].plot(\n", | ||
| " kind=\"bar\", stacked=True, ax=ax, title=agent, xlabel=\"Year\", ylabel=\"Capacity\"\n", | ||
| " )\n", |
There was a problem hiding this comment.
Not too concerned about this. If there was only one agent then you'd plot in a different way anyway
| "We begin by loading the `model.toml` input file to get the list of milestone years.\n", | ||
| "\n", | ||
| "[output-format]: https://energysystemsmodellinglab.github.io/MUSE2/file_formats/output_files.html" | ||
| "Output files are mostly in CSV format. The format of output files is documented [here][output-format]." |
There was a problem hiding this comment.
Should remove this comment as it isn't true
| "merged = asset_capacities.merge(assets, on=[\"asset_id\", \"group_id\"])\n", | ||
| "agg_capacities = merged.groupby([\"milestone_year\", \"agent_id\", \"process_id\"])[\n", | ||
| " \"capacity\"\n", | ||
| "].sum()\n", | ||
| "agg_capacities_wide = agg_capacities.unstack([\"agent_id\", \"process_id\"], fill_value=0)\n", |
| "agents = agg_capacities_wide.columns.get_level_values(\"agent_id\").unique()\n", | ||
| "fig, axes = plt.subplots(1, len(agents), figsize=(4 * len(agents), 4))\n", | ||
| "for ax, agent in zip(axes, agents):\n", | ||
| " capacity[capacity[\"agent_id\"] == agent].pivot(\n", | ||
| " index=\"year\", columns=\"process_id\", values=\"capacity\"\n", | ||
| " ).plot(kind=\"bar\", ax=ax)\n", | ||
| " ax.set_title(agent)\n", | ||
| " ax.set_xlabel(\"Year\")\n", | ||
| " ax.set_ylabel(\"Capacity\")\n", | ||
| " ax.legend(title=\"Process\")" | ||
| " agg_capacities_wide[agent].plot(\n", | ||
| " kind=\"bar\", stacked=True, ax=ax, title=agent, xlabel=\"Year\", ylabel=\"Capacity\"\n", | ||
| " )\n", |
There was a problem hiding this comment.
Not too concerned about this. If there was only one agent then you'd plot in a different way anyway
for more information, see https://pre-commit.ci
| " agg_capacities_wide[agent].plot(\n", | ||
| " kind=\"bar\", stacked=True, ax=ax, title=agent, xlabel=\"Year\", ylabel=\"Capacity\"\n", | ||
| " )\n", |

Description
Update the capacity notebook to account for the new output file structure - which is far from ideal from the processing perspective. Performance-wise, there are vectorised options that are faster than
apply, but this one was more readable.The output plot is:
Close #75
Type of change
Key checklist
python -m pytest)pre-commit run --all-files)Further checks
(Indicate issue here: # (issue))