Skip to content

Commit

Permalink
Fix SimaPro allocation
Browse files Browse the repository at this point in the history
- Can allocate functional inputs
- Don't allocate nonfunctional production
  • Loading branch information
cmutel committed Jun 17, 2024
1 parent 0c1bbf8 commit 5cb0947
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 18 deletions.
21 changes: 18 additions & 3 deletions bw2io/strategies/simapro.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@
detoxify_re = re.compile(detoxify_pattern)


def functional(exc: dict) -> bool:
"""Determine if an exchange is functional by looking at `type` and `functional` attributes."""
if exc.get("functional"):
return True
# Backwards compatibility, but makes me uncomfortable. Much better to label explicitly.
elif "functional" not in exc and exc["type"] == "production":
return True
return False


def sp_allocate_products(db):
"""
Allocate products in a SimaPro dataset by creating a separate dataset for each product.
Expand Down Expand Up @@ -86,7 +96,9 @@ def sp_allocate_products(db):
if not ds["type"] == "multifunctional":
continue
products = [
exc for exc in ds.get("exchanges", []) if exc["type"] == "production"
exc
for exc in ds.get("exchanges", [])
if functional(exc)
]
for product in products:
if not isinstance(product.get("allocation"), Number):
Expand All @@ -106,15 +118,18 @@ def sp_allocate_products(db):
continue

new = copy.deepcopy(ds)
new["exchanges"] = [copy.deepcopy(product).pop("allocation")] + [
production_exc = copy.deepcopy(product)
del production_exc['allocation']
new["exchanges"] = [production_exc] + [
rescale_exchange(exc, allocation)
for exc in new["exchanges"]
if exc["type"] != "production"
if not functional(exc)
]
# Just how SimaPro rolls...
new["name"] = new["reference product"] = product["name"]
new["unit"] = product["unit"]
new["production amount"] = product["amount"]
new["type"] = "process"
new_data.append(new)

return db + new_data
Expand Down
15 changes: 0 additions & 15 deletions tests/simapro.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,6 @@
SP_FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "fixtures", "simapro")


@bw2test
def test_sp_import_allocation():
Migration("default-units").write(
get_default_units_migration_data(), "Convert to default units"
)

sp = SimaProCSVImporter(
os.path.join(SP_FIXTURES_DIR, "allocation.csv"), normalize_biosphere=False
)
sp.apply_strategies()
assert sp.all_linked
assert sp.statistics() == (3, 5, 0)
sp.write_database()


@bw2test
def test_sp_wrong_field_ordering():
sp = SimaProCSVImporter(os.path.join(SP_FIXTURES_DIR, "new-order.csv"))
Expand Down
171 changes: 171 additions & 0 deletions tests/strategies/simapro_allocation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
from bw2io.strategies.simapro import sp_allocate_products


def test_sp_allocate_products():
given = [
{
"type": "multifunctional",
"exchanges": [
{
"name": "Biowaste",
"unit": "kg",
"comment": "Manure",
"amount": 10,
"uncertainty type": 0,
"loc": 10,
"type": "production",
"functional": False,
},
{
"name": "Quack",
"unit": "p",
"amount": 5,
"uncertainty type": 0,
"loc": 5,
"type": "technosphere",
},
{
"name": "Wool",
"unit": "kg",
"amount": 1000.0,
"allocation": 3,
"type": "production",
"functional": True,
},
{
"name": "Strips",
"unit": "kg",
"amount": 2000.0,
"allocation": 2,
"type": "technosphere",
"functional": True,
},
{
"name": "Viscera",
"unit": "kg",
"amount": 3000.0,
"allocation": 0,
"type": "production",
"functional": True,
},
],
}
]
expected = [
{
"type": "multifunctional",
"exchanges": [
{
"name": "Biowaste",
"unit": "kg",
"comment": "Manure",
"amount": 10,
"uncertainty type": 0,
"loc": 10,
"type": "production",
"functional": False,
},
{
"name": "Quack",
"unit": "p",
"amount": 5,
"uncertainty type": 0,
"loc": 5,
"type": "technosphere",
},
{
"name": "Wool",
"unit": "kg",
"amount": 1000.0,
"allocation": 3,
"type": "production",
"functional": True,
},
{
"name": "Strips",
"unit": "kg",
"amount": 2000.0,
"allocation": 2,
"type": "technosphere",
"functional": True,
},
{
"name": "Viscera",
"unit": "kg",
"amount": 3000.0,
"allocation": 0,
"type": "production",
"functional": True,
},
],
},
{
"type": "process",
"exchanges": [
{
"name": "Wool",
"unit": "kg",
"amount": 1000.0,
"type": "production",
"functional": True,
},
{
"name": "Biowaste",
"unit": "kg",
"comment": "Manure",
"amount": 6.,
"uncertainty type": 0,
"loc": 6.,
"type": "production",
"functional": False,
},
{
"name": "Quack",
"unit": "p",
"amount": 3.,
"uncertainty type": 0,
"loc": 3.,
"type": "technosphere",
},
],
"name": "Wool",
"reference product": "Wool",
"unit": "kg",
"production amount": 1000.0,
},
{
"type": "process",
"exchanges": [
{
"name": "Strips",
"unit": "kg",
"amount": 2000.0,
"type": "technosphere",
"functional": True,
},
{
"name": "Biowaste",
"unit": "kg",
"comment": "Manure",
"amount": 4.,
"uncertainty type": 0,
"loc": 4.,
"type": "production",
"functional": False,
},
{
"name": "Quack",
"unit": "p",
"amount": 2.,
"uncertainty type": 0,
"loc": 2.,
"type": "technosphere",
},
],
"name": "Strips",
"reference product": "Strips",
"unit": "kg",
"production amount": 2000.0,
},
]
assert sp_allocate_products(given) == expected

0 comments on commit 5cb0947

Please sign in to comment.