Skip to content

Commit

Permalink
Evaluate allocation formulae
Browse files Browse the repository at this point in the history
  • Loading branch information
cmutel committed Jun 16, 2024
1 parent 83720c6 commit ba46049
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 35 deletions.
4 changes: 4 additions & 0 deletions bw_simapro_csv/blocks/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,14 @@ def resolve_local_parameters(self, global_params: dict, substitutes: dict) -> No
if not getattr(block, "has_formula", None):
continue
prepare_formulas(block.parsed, self.header)
prepare_formulas(block.parsed, self.header, formula_field="allocation_formula")
for obj in block.parsed:
if "formula" in obj:
substitute_in_formulas(obj, visitor)
obj["amount"] = interpreter(obj["formula"])
if "allocation_formula" in obj:
substitute_in_formulas(obj, visitor, formula_field="allocation_formula")
obj["allocation"] = interpreter(obj["allocation_formula"])
if "field1" in obj:
# We can only now construct and validate an uncertainty distribution,
# because we finally have an `amount` field.
Expand Down
33 changes: 19 additions & 14 deletions bw_simapro_csv/blocks/products.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,23 @@ def __init__(self, block: list[tuple], header: dict, **kwargs):
self.has_formula = True

for line_no, line in skip_empty(block):
self.parsed.append(
add_amount_or_formula(
{
"name": line[0],
"unit": line[1],
"allocation_raw": line[3],
"waste_type": line[4],
"category": line[5],
"comment": line[6],
"line_no": line_no,
},
line[2],
header["decimal_separator"],
)
ds = add_amount_or_formula(
{
"name": line[0],
"unit": line[1],
"waste_type": line[4],
"category": line[5],
"comment": line[6],
"line_no": line_no,
},
line[2],
header["decimal_separator"],
)
ds = add_amount_or_formula(
data=ds,
value=line[3],
decimal_separator=header["decimal_separator"],
amount_key="allocation",
formula_key="allocation_formula",
)
self.parsed.append(ds)
45 changes: 24 additions & 21 deletions bw_simapro_csv/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def fix_iff_formula(formula: str, pattern: Pattern) -> str:
return formula


def prepare_formulas(block: list[dict], header: dict) -> list[dict]:
def prepare_formulas(block: list[dict], header: dict, formula_field: str = "formula") -> list[dict]:
"""Make necessary conversions so formulas can be parsed by Python.
Does the following:
Expand All @@ -123,26 +123,26 @@ def prepare_formulas(block: list[dict], header: dict) -> list[dict]:
iff_re = compile_iff_re(header)

for obj in block:
if "formula" in obj:
if "^" in obj["formula"]:
new_formula = obj["formula"].replace("^", "**")
logger.info(
if formula_field in obj:
if "^" in obj[formula_field]:
new_formula = obj[formula_field].replace("^", "**")
logger.debug(
f"""Replacing `^` in formula on line {obj['line_no']}:
{obj['formula']} >>> {new_formula}"""
{obj[formula_field]} >>> {new_formula}"""
)
if "original_formula" not in obj["formula"]:
obj["original_formula"] = obj["formula"]
obj["formula"] = new_formula
if f"original_{formula_field}" not in obj:
obj[f"original_{formula_field}"] = obj[formula_field]
obj[formula_field] = new_formula

new_formula = fix_iff_formula(obj["formula"], iff_re)
if new_formula != obj["formula"]:
logger.info(
new_formula = fix_iff_formula(obj[formula_field], iff_re)
if new_formula != obj[formula_field]:
logger.debug(
f"""Replacing `Iff` expression in formula on line {obj['line_no']}:
{obj['formula']} >>> {new_formula}"""
{obj[formula_field]} >>> {new_formula}"""
)
if "original_formula" not in obj["formula"]:
obj["original_formula"] = obj["formula"]
obj["formula"] = new_formula
if f"original_{formula_field}" not in obj:
obj[f"original_{formula_field}"] = obj[formula_field]
obj[formula_field] = new_formula

return block

Expand Down Expand Up @@ -176,8 +176,8 @@ def __call__(self, formula):
return unparse(parsed).strip()


def substitute_in_formulas(obj: dict, visitor: Type) -> dict:
"""Substitute variable names in `obj['formula']` based on `substitutions`.
def substitute_in_formulas(obj: dict, visitor: Type, formula_field: str = "formula") -> dict:
"""Substitute variable names in `obj[formula_field]` based on `substitutions`.
Keeps `original_formula`.
Expand All @@ -191,8 +191,11 @@ def substitute_in_formulas(obj: dict, visitor: Type) -> dict:
{'formula': 'hi_mom * 2', 'original_formula': 'a * 2'}
"""
if "formula" in obj:
obj["original_formula"] = obj["formula"]
obj["formula"] = visitor(obj["formula"])
if formula_field in obj:
obj[f"original_{formula_field}"] = obj[formula_field]
obj[formula_field] = visitor(obj[formula_field])

if obj[f"original_{formula_field}"] == obj[formula_field]:
del obj[f"original_{formula_field}"]

return obj

0 comments on commit ba46049

Please sign in to comment.