Skip to content

Commit 08800cc

Browse files
committed
corrected issue with unit conversion factors in elementary flows contribution analysis
1 parent f370cf6 commit 08800cc

File tree

3 files changed

+78
-19
lines changed

3 files changed

+78
-19
lines changed

mescal/impact_assessment.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -342,26 +342,26 @@ def compute_impact_scores(
342342
)
343343

344344
if contribution_analysis:
345-
df_contrib_analysis_results_constr = pd.concat( # concatenate the contribution analysis results
346-
[df_contrib_analysis_results_constr]+df_comp_list,
347-
ignore_index=True
348-
)
345+
df_comp_all = pd.concat(df_comp_list) # concatenate composition results in a single dataframe
349346

350-
df_contrib_analysis_results_constr = pd.merge(
351-
left=df_contrib_analysis_results_constr,
347+
df_comp_all = pd.merge( # adding the unit conversion factors to the dataframe
348+
left=df_comp_all,
352349
right=unit_conversion[['Name', 'Type', 'Value']],
353350
left_on=['act_name', 'act_type'],
354351
right_on=['Name', 'Type'],
355352
how='left',
356353
)
357354

358-
# Multiply the score and amount columns by the conversion factor
359-
df_contrib_analysis_results_constr['score'] = (df_contrib_analysis_results_constr['score']
360-
* df_contrib_analysis_results_constr['Value'])
361-
df_contrib_analysis_results_constr['amount'] = (df_contrib_analysis_results_constr['amount']
362-
* df_contrib_analysis_results_constr['Value'])
355+
# Multiply the score and amount columns by the conversion factor in the composition dataframe
356+
df_comp_all['score'] = (df_comp_all['score'] * df_comp_all['Value'])
357+
df_comp_all['amount'] = (df_comp_all['amount'] * df_comp_all['Value'])
363358

364-
df_contrib_analysis_results_constr.drop(columns=['Value', 'Name', 'Type'], inplace=True)
359+
df_comp_all.drop(columns=['Value', 'Name', 'Type'], inplace=True)
360+
361+
df_contrib_analysis_results_constr = pd.concat( # concatenate the contribution analysis results
362+
[df_contrib_analysis_results_constr, df_comp_all],
363+
ignore_index=True
364+
)
365365

366366
if lifetime is None:
367367
pass

tests/test_impact_assessment.py

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,36 @@
66
from mescal.filesystem_constants import BW_PROJECT_NAME
77

88
dummy_esm_db = [
9+
{
10+
"name": "BATTERY, Construction",
11+
"reference product": "battery, Li-ion, LFP, rechargeable, prismatic",
12+
"location": "GLO",
13+
"database": "dummy_esm_db",
14+
"unit": "kilogram",
15+
"code": "00000",
16+
"exchanges": [
17+
{
18+
"name": "BATTERY, Construction",
19+
"product": "battery, Li-ion, LFP, rechargeable, prismatic",
20+
"location": "GLO",
21+
"database": "dummy_esm_db",
22+
"type": "production",
23+
"amount": 1,
24+
"unit": "kilogram",
25+
"code": "00000"
26+
},
27+
{
28+
"name": "market for battery, Li-ion, LFP, rechargeable, prismatic",
29+
"product": "battery, Li-ion, LFP, rechargeable, prismatic",
30+
"location": "GLO",
31+
"database": "ecoinvent-3.9.1-cutoff",
32+
"type": "technosphere",
33+
"amount": 1,
34+
"unit": "kilogram",
35+
"code": 'f22991a7a4e1d7ecfa81cdd7453e83d2',
36+
}
37+
]
38+
},
939
{
1040
"name": "TRAIN_FREIGHT_DIESEL_LOC, Construction",
1141
"reference product": "locomotive",
@@ -69,6 +99,8 @@
6999
]
70100

71101
mapping = [
102+
['BATTERY', 'Construction', 'battery, Li-ion, LFP, rechargeable, prismatic',
103+
'market for battery, Li-ion, LFP, rechargeable, prismatic', 'GLO', 'ecoinvent-3.9.1-cutoff', '00000'],
72104
['TRAIN_FREIGHT_DIESEL_LOC', 'Construction', 'locomotive', 'locomotive production', 'RER',
73105
'ecoinvent-3.9.1-cutoff', '00001'],
74106
['TRAIN_FREIGHT_DIESEL_WAG', 'Construction', 'goods wagon', 'goods wagon production', 'RER',
@@ -80,12 +112,14 @@
80112
]
81113

82114
unit_conversion = [
115+
['BATTERY', 'Construction', 10, 'kilogram', 'kilowatt hour'],
83116
['TRAIN_FREIGHT_DIESEL_LOC', 'Construction', 2, 'unit', 'unit'],
84117
['TRAIN_FREIGHT_DIESEL_WAG', 'Construction', 20, 'unit', 'unit'],
85118
['TRAIN_FREIGHT_DIESEL', 'Construction', 2.5e-5, 'unit', 'ton kilometer per hour'],
86119
]
87120

88121
lifetime = [
122+
['BATTERY', 30, 20],
89123
['TRAIN_FREIGHT_DIESEL', 40, None],
90124
['TRAIN_FREIGHT_DIESEL_LOC', None, 50],
91125
['TRAIN_FREIGHT_DIESEL_WAG', None, 50],
@@ -128,21 +162,46 @@ def test_compute_impact_score():
128162
contribution_analysis=True,
129163
)
130164

131-
lcia_value = R[
165+
lcia_value_train = R[
132166
(R.Impact_category == ('IPCC 2021', 'climate change', 'global warming potential (GWP100)'))
133167
& (R.Name == 'TRAIN_FREIGHT_DIESEL')
134168
& (R.Type == 'Construction')
135169
].Value.iloc[0]
136170

137-
assert 44.40 <= lcia_value <= 44.41
171+
assert 44.40 <= lcia_value_train <= 44.41
138172

139-
max_contrib = df_contrib_results[
173+
contrib_train = df_contrib_results[
140174
(df_contrib_results.impact_category == ('IPCC 2021', 'climate change', 'global warming potential (GWP100)'))
141175
& (df_contrib_results.act_name == 'TRAIN_FREIGHT_DIESEL')
142176
& (df_contrib_results.act_type == 'Construction')
143-
& (df_contrib_results.score == df_contrib_results.score.max())
144177
]
145178

146-
assert max_contrib.ef_name.iloc[0] == 'Carbon dioxide, fossil'
147-
assert max_contrib.ef_categories.iloc[0] == ('air', 'non-urban air or from high stacks')
148-
assert 17.42 <= max_contrib.score.iloc[0] <= 17.43
179+
max_contrib_train = contrib_train[
180+
(contrib_train.score == contrib_train.score.max())
181+
]
182+
183+
assert max_contrib_train.ef_name.iloc[0] == 'Carbon dioxide, fossil'
184+
assert max_contrib_train.ef_categories.iloc[0] == ('air', 'non-urban air or from high stacks')
185+
assert 17.42 <= max_contrib_train.score.iloc[0] <= 17.43
186+
187+
lcia_value_batt = R[
188+
(R.Impact_category == ('IPCC 2021', 'climate change', 'global warming potential (GWP100)'))
189+
& (R.Name == 'BATTERY')
190+
& (R.Type == 'Construction')
191+
].Value.iloc[0]
192+
193+
assert 167.60 <= lcia_value_batt <= 167.61
194+
195+
contrib_batt = df_contrib_results[
196+
(df_contrib_results.impact_category == ('IPCC 2021', 'climate change', 'global warming potential (GWP100)'))
197+
& (df_contrib_results.act_name == 'BATTERY')
198+
& (df_contrib_results.act_type == 'Construction')
199+
]
200+
201+
max_contrib_batt = contrib_batt[
202+
(contrib_batt.score == contrib_batt.score.max())
203+
]
204+
205+
assert max_contrib_batt.ef_name.iloc[0] == 'Carbon dioxide, fossil'
206+
assert max_contrib_batt.ef_categories.iloc[0] == ('air', 'non-urban air or from high stacks')
207+
assert 98.78 <= max_contrib_batt.score.iloc[0] <= 98.79

tests/test_impact_assessment.xlsx

283 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)