Skip to content

Commit 07b39a3

Browse files
authored
Fix inconsistent reading of agent share names (#586)
* Remove to_agent_share conversion * Remove inline comment * Fix error in trade model * Update documentation * Update reader tests * More helpful error message * More helpful error message
1 parent ad79dc4 commit 07b39a3

File tree

9 files changed

+39
-49
lines changed

9 files changed

+39
-49
lines changed

docs/inputs/technodata.rst

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -136,33 +136,32 @@ InterestRate
136136
is the technology interest rate (called hurdle rates in other models).
137137
This is used for the interest used in the discount rate and corresponds to the interest built when borrowing money.
138138

139-
Agent_0, ..., Agent_N
140-
represent the allocation of the initial capacity to the each agent.
141-
The column heading refers each retrofit agent "AgentShare" as defined in the agents' definition (see :ref:`inputs-agents`).
139+
Agent0, ..., AgentN
140+
represent the proportion of initial capacity allocated to each agent.
141+
Must match AgentShare names specified in the :ref:`inputs-agents` file.
142+
All agents must be represented in the table.
143+
If using "New" and "Retrofit" agents, you should create a column with the name of each "Retrofit" agent share.
144+
If only using "New" agents, you should create a column with the name of each "New" agent share.
142145
The value corresponds to the ownership of the initial stock, as defined in the :ref:`inputs-existing-capacity` for the starting year of the simulation.
143-
For example, if an initial boiler stock of 10 PJ is available, this is allocated to each agent according to the "AgentShare".
144146

145-
In a one-agent simulation, assuming that the *AgentShare* equals to *Agent_2* for the retrofit agent, the technodata should indicate the stock ownership as follows.
146-
The modelled agent would own the total 10 PJ of the initial stock of boilers.
147+
For example, in a one-agent simulation, you should specify the following to indicate full ownership of existing capacity by the agent (assuming an agent share name of "Agent1"):
147148

148149
.. csv-table:: Techno-data: AgentShare - 1 agent
149-
:header: ProcessName, RegionName, Time, ..., Agent_2
150+
:header: ProcessName, RegionName, Time, ..., Agent1
150151

151152
resBoilerElectric, region1, 2010, ..., 1
152153
resBoilerElectric, region1, 2030, ..., 1
153154

154-
In a two-agent simulation, a new column needs to be added for each retrofit agent belonging to the new-retrofit agent pair.
155-
The column heading refers each retrofit agent "AgentShare" as defined in the agents' definition (see :ref:`inputs-agents`).
156-
Assuming a split of the initial capacity into 30 \% and 70 \% for each retrofit agent, the model table would be setup as follows.
157-
The values of the "AgentShare" needs to reflect the demand split represented by the "Quantity" attribute (see :ref:`inputs-agents`),
158-
to make sure that the initial demand is fulfilled with the initial stock.
155+
In a two-agent simulation, assuming a 30\% / 70\% split of initial capacity between the two agents, the table would be as follows:
159156

160157
.. csv-table:: Techno-data: AgentShare - 2 agents
161-
:header: ProcessName, RegionName, Time, ..., Agent_2, Agent_4
158+
:header: ProcessName, RegionName, Time, ..., Agent1, Agent2
162159

163160
resBoilerElectric, region1, 2010, ..., 0.3, 0.7
164161
resBoilerElectric, region1, 2030, ..., 0.3, 0.7
165162

163+
Values must sum to 1 for each row of the table.
164+
166165
The input data has to be provided for the base year. Additional years within the time
167166
framework of the overall simulation can be defined. In this case, MUSE would interpolate
168167
the values between the provided periods and assume a constant value afterwards. The additional

src/muse/agents/factories.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from muse.agents.agent import Agent, InvestingAgent
1010
from muse.defaults import DEFAULT_SECTORS_DIRECTORY
11-
from muse.errors import RetrofitAgentNotDefined, TechnologyNotDefined
11+
from muse.errors import AgentShareNotDefined, TechnologyNotDefined
1212

1313

1414
def create_standard_agent(
@@ -342,7 +342,7 @@ def _shared_capacity(
342342
try:
343343
shares = technologies[share]
344344
except KeyError:
345-
raise RetrofitAgentNotDefined
345+
raise AgentShareNotDefined
346346

347347
try:
348348
shares = shares.sel(technology=capacity.technology)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
AgentShare,Name,RegionName,Objective,ObjData,Objsort,SearchRule,DecisionMethod,MaturityThreshold,SpendLimit,Type
2-
agent_share,A1,R1,ALCOE,1,TRUE,from_assets->compress->reduce_assets,singleObj,-1,inf,default
3-
agent_share,A1,R2,ALCOE,1,TRUE,from_assets->compress->reduce_assets,singleObj,-1,inf,default
2+
Agent1,A1,R1,ALCOE,1,TRUE,from_assets->compress->reduce_assets,singleObj,-1,inf,default
3+
Agent1,A1,R2,ALCOE,1,TRUE,from_assets->compress->reduce_assets,singleObj,-1,inf,default
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ProcessName,RegionName,Time,var_par,var_exp,TechnicalLife,UtilizationFactor,ScalingSize,efficiency,InterestRate,Type,Fuel,EndUse,AgentShare
2-
Unit,-,Year,MUS$2010/PJ,-,Years,-,PJ,%,-,-,-,-,-
1+
ProcessName,RegionName,Time,var_par,var_exp,TechnicalLife,UtilizationFactor,ScalingSize,efficiency,InterestRate,Type,Fuel,EndUse,Agent1
2+
Unit,-,Year,MUS$2010/PJ,-,Years,-,PJ,%,-,-,-,-,New
33
gassupply1,R1,2010,3,1,10,0.9,0.00000189,86,0.1,energy,gas,gas,1
44
gassupply1,R2,2010,3,1,10,0.9,0.00000189,86,0.1,energy,gas,gas,1

src/muse/data/example/trade/technodata/power/Technodata.csv

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
ProcessName,RegionName,Time,cap_exp,fix_exp,var_par,var_exp,TechnicalLife,UtilizationFactor,ScalingSize,efficiency,InterestRate,Type,Fuel,EndUse,AgentShare
2-
Unit,-,Year,-,-,MUS$2010/PJ,-,Years,-,PJ,%,-,-,-,-,
1+
ProcessName,RegionName,Time,cap_exp,fix_exp,var_par,var_exp,TechnicalLife,UtilizationFactor,ScalingSize,efficiency,InterestRate,Type,Fuel,EndUse,Agent1
2+
Unit,-,Year,-,-,MUS$2010/PJ,-,Years,-,PJ,%,-,-,-,-,New
33
gasCCGT,R1,2010,1,1,0,1,35,0.9,0.00000189,86,0.1,energy,gas,electricity,1
44
windturbine,R1,2010,1,1,0,1,25,0.4,0.00000189,86,0.1,energy,wind,electricity,1
55
gasCCGT,R2,2010,1,1,0,1,35,0.9,0.00000189,86,0.1,energy,gas,electricity,1
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
AgentShare,Name,RegionName,Objective1,Objective2,Objective3,ObjData1,ObjData2,ObjData3,Objsort1,Objsort2,Objsort3,SearchRule,DecisionMethod,Quantity,MaturityThreshold,Budget,Type
2-
agent_share_1,A1,R1,LCOE,,,1,,,TRUE,,,all,singleObj,1,-1,inf,New
3-
agent_share_2,A1,R1,LCOE,,,1,,,TRUE,,,all,singleObj,1,-1,inf,Retrofit
4-
agent_share_1,A1,R2,LCOE,,,1,,,TRUE,,,all,singleObj,1,-1,inf,New
5-
agent_share_2,A1,R2,LCOE,,,1,,,TRUE,,,all,singleObj,1,-1,inf,Retrofit
2+
Agent1,A1,R1,LCOE,,,1,,,TRUE,,,all,singleObj,1,-1,inf,New
3+
Agent2,A1,R1,LCOE,,,1,,,TRUE,,,all,singleObj,1,-1,inf,Retrofit
4+
Agent1,A1,R2,LCOE,,,1,,,TRUE,,,all,singleObj,1,-1,inf,New
5+
Agent2,A1,R2,LCOE,,,1,,,TRUE,,,all,singleObj,1,-1,inf,Retrofit

src/muse/errors.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
class RetrofitAgentNotDefined(Exception):
2-
"""Indicates that the retrofit agent has not been defined."""
3-
4-
msg = """The retrofit agent has not been defined. This might be because it actually
5-
has not been defined in the agents file or specified in the technodata file or it cannot
6-
be found because there is a typo in its name in either the agents and or technodata
7-
files. When a retrofit agent is defined in the agent file, the same name should be
8-
reported as an additional column in the technodata, assigning the fraction of the
9-
initial stock assigned to each retrofit agent. In presence of multiple retrofit agents,
10-
a new column needs to be added per agent."""
1+
class AgentShareNotDefined(Exception):
2+
"""Indicates that an agent share is missing from a technodata file."""
3+
4+
msg = """All agents must be represented in the technodata file.
5+
If using "New" and "Retrofit" agents, you need a column with the name of each "Retrofit"
6+
agent share. If only using "New" agents, you need a column with the name of each "New"
7+
agent share. Please check that all agents are represented in the technodata file, and
8+
that the agent share names match those specified in your agents file.
9+
"""
1110

1211
def __str__(self):
1312
return self.msg

src/muse/readers/csv.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,12 @@ def read_technodictionary(filename: Union[str, Path]) -> xr.Dataset:
7474
7575
There are three axes: technologies, regions, and year.
7676
"""
77-
from re import sub
78-
7977
from muse.readers import camel_to_snake
8078

81-
def to_agent_share(name):
82-
return sub(r"agent(\d)", r"agent_share_\1", name)
83-
8479
csv = pd.read_csv(filename, float_precision="high", low_memory=False)
8580
csv.drop(csv.filter(regex="Unname"), axis=1, inplace=True)
86-
csv = (
87-
csv.rename(columns=camel_to_snake)
88-
.rename(columns=to_agent_share)
89-
.rename(columns={"end_use": "enduse", "availabiliy year": "availability"})
81+
csv = csv.rename(columns=camel_to_snake).rename(
82+
columns={"end_use": "enduse", "availabiliy year": "availability"}
9083
)
9184
data = csv[csv.process_name != "Unit"]
9285

@@ -533,7 +526,7 @@ def read_csv_agent_parameters(filename) -> list:
533526
Returns a list of dictionaries, where each dictionary can be used to instantiate an
534527
agent in :py:func:`muse.agents.factories.factory`.
535528
"""
536-
from re import sub
529+
from muse.readers import camel_to_snake
537530

538531
if (
539532
isinstance(filename, str)
@@ -599,8 +592,7 @@ def read_csv_agent_parameters(filename) -> list:
599592
data["maturity_threshold"] = row.MaturityThreshold
600593
if hasattr(row, "SpendLimit"):
601594
data["spend_limit"] = row.SpendLimit
602-
# if agent_type != "newcapa":
603-
data["share"] = sub(r"Agent(\d)", r"agent_share_\1", row.AgentShare)
595+
data["share"] = camel_to_snake(row.AgentShare)
604596
if agent_type == "retrofit" and data["decision"] == "lexo":
605597
data["decision"] = "retro_lexo"
606598
result.append(data)

tests/test_readers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ def test_read_technodictionary(default_model):
455455
type=np.dtype("O"),
456456
fuel=np.dtype("<U11"),
457457
enduse=np.dtype("<U4"),
458-
agent_share_1=np.dtype("int64"),
458+
agent1=np.dtype("int64"),
459459
tech_type=np.dtype("<U6"),
460460
efficiency=np.dtype("int64"),
461461
max_capacity_addition=np.dtype("int64"),
@@ -602,7 +602,7 @@ def test_read_csv_agent_parameters(default_model):
602602
"quantity": 1,
603603
"maturity_threshold": -1,
604604
"spend_limit": np.inf,
605-
"share": "agent_share_1",
605+
"share": "agent1",
606606
},
607607
]
608608

0 commit comments

Comments
 (0)