def install_fixtures(self):
     db = Database("a")
     db.write(lci_fixture)
     method = Method(("method", ))
     method.register()
     method.write(method_fixture)
     return db, method
    def test_fix_spatial_dictionaries(self):
        # TODO: Fix
        return

        empty = Database("empty")
        empty.register(depends=[], geocollections=["foo"])
        method = Method(("a", "name"))
        method.register(geocollections=["foo"])
        rlca = RegionalizationBase({("empty", "nothing"): 1},
                                   method=("a", "name"))

        # No-op - `inv_spatial_dict` not yet set...
        rlca.fix_spatial_dictionaries()
        assert not getattr(rlca, "_mapped_spatial_dict", None)
        self.assertFalse(hasattr(rlca, "inv_spatial_dict"))

        geomapping.data = {"a": 1, "b": 2}
        rlca.inv_spatial_dict = {"a": "foo"}
        # Now it does something...
        rlca.fix_spatial_dictionaries()
        self.assertFalse(hasattr(rlca, "ia_spatial_dict"))
        rlca.inv_spatial_dict = {1: "foo"}
        rlca.ia_spatial_dict = {2: "bar"}
        rlca.fix_spatial_dictionaries()
        self.assertEqual(rlca.inv_spatial_dict, {"a": "foo"})
        self.assertEqual(rlca.ia_spatial_dict, {"b": "bar"})
Esempio n. 3
0
    def write_methods(self, overwrite=False, verbose=True):
        num_methods, num_cfs, num_unlinked = self.statistics(False)
        if num_unlinked:
            raise ValueError((u"Can't write unlinked methods ({} unlinked cfs)"
                              ).format(num_unlinked))
        for ds in self.data:
            if ds["name"] in methods:
                if overwrite:
                    del methods[ds["name"]]
                else:
                    raise ValueError(
                        (u"Method {} already exists. Use "
                         u"``overwrite=True`` to overwrite existing methods"
                         ).format(ds["name"]))

            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                method = Method(ds["name"])
                method.register(
                    description=ds["description"],
                    filename=ds["filename"],
                    unit=ds["unit"],
                )
                method.write(self._reformat_cfs(ds["exchanges"]))
                method.process()
        if verbose:
            print(u"Wrote {} LCIA methods with {} characterization factors".
                  format(num_methods, num_cfs))
def activity_and_method():
    database = DatabaseChooser("db")
    database.write({
        ("db", "a"): {
            'exchanges': [{
                'input': ("db", "a"),
                'amount': 2,
                'type': 'production',
            }, {
                'input': ("db", "b"),
                'amount': 3,
                'type': 'technosphere',
            }, {
                'input': ("db", "c"),
                'amount': 4,
                'type': 'biosphere',
            }],
            'name': 'a'
        },
        ("db", "b"): {'name': 'b'},
        ("db", "c"): {'name': 'c', 'type': 'biosphere'},
        ("db", "d"): {
            'name': 'd',
            'exchanges': [{
                'input': ("db", "a"),
                'amount': 5,
                'type': 'technosphere'
            }]
        },
    })
    cfs = [(("db", "c"), 42)]
    method = Method(("a method",))
    method.register()
    method.write(cfs)
    return database.get("a"), method
Esempio n. 5
0
    def test_grouping_separate_unit(self):
        biosphere_data = {
            ("biosphere", "1"): {
                "categories": ["foo", "this"],
                "exchanges": [],
                "name": "some bad stuff",
                "type": "emission",
                "unit": "kg",
            },
            ("biosphere", "2"): {
                "categories": ["foo", "that"],
                "exchanges": [],
                "name": "some bad stuff",
                "type": "emission",
                "unit": "tonne",
            },
        }

        biosphere = Database("biosphere")
        biosphere.register(name="Tests", depends=[])
        biosphere.write(biosphere_data)

        method = Method(("test", "LCIA", "method"))
        method.register(unit="points")
        method.write([(("biosphere", "1"), 1.0, "GLO"),
                      (("biosphere", "2"), 2.0, "GLO")])

        answer = {
            ("some bad stuff", "foo", "kg"): [1.0],
            ("some bad stuff", "foo", "tonne"): [2.0],
        }
        self.assertEqual(group_by_emissions(method), answer)
 def test_health_check(self):
     db = Database("a")
     db.write(lci_fixture)
     method = Method(("method",))
     method.register()
     method.write(method_fixture)
     dhc = DHCMock("a").check()
    def test_geocollections_mismatch(self):
        inventory = Database("inventory")
        inventory.register(geocollections=["places"])
        method = Method(("a", "method"))
        method.register(geocollections=['regions'])

        with self.assertRaises(GeocollectionsMismatch):
            LCA({("inventory", "foo"): 1}, method=("a", "method"))
Esempio n. 8
0
def add_example_database(overwrite=True):
    from ..importers.excel import (
        assign_only_product_as_production,
        convert_activity_parameters_to_list,
        convert_uncertainty_types_to_integers,
        csv_add_missing_exchanges_section,
        csv_drop_unknown,
        csv_numerize,
        csv_restore_booleans,
        csv_restore_tuples,
        drop_falsey_uncertainty_fields_but_keep_zeros,
        ExcelImporter,
        set_code_by_activity_hash,
        strip_biosphere_exc_locations,
    )

    if "Mobility example" in databases:
        if not overwrite:
            print("Example already imported, use `overwrite=True` to delete")
            return
        else:
            del databases["Mobility example"]
            if ("IPCC", "simple") in methods:
                del methods[("IPCC", "simple")]

    importer = ExcelImporter(
        os.path.join(dirpath, "examples",
                     "sample_parameterized_database.xlsx"))
    importer.strategies = [
        csv_restore_tuples,
        csv_restore_booleans,
        csv_numerize,
        csv_drop_unknown,
        csv_add_missing_exchanges_section,
        strip_biosphere_exc_locations,
        set_code_by_activity_hash,
        assign_only_product_as_production,
        drop_falsey_uncertainty_fields_but_keep_zeros,
        convert_uncertainty_types_to_integers,
        convert_activity_parameters_to_list,
    ]
    importer.apply_strategies()
    importer.match_database(fields=['name'])
    importer.write_database(activate_parameters=True)

    group = "Mobility exchanges"
    Group.delete().where(Group.name == group).execute()
    group = Group.create(name=group)

    for ds in Database("Mobility example"):
        parameters.add_exchanges_to_group(group, ds)

    parameters.recalculate()

    ipcc = Method(("IPCC", "simple"))
    ipcc.register()
    ipcc.write([(("Mobility example", "CO2"), 1)])
 def test_site_generic_method_error(self):
     empty = Database("empty")
     empty.register(depends=[], geocollections=[])
     method = Method(("a", "name"))
     method.register()
     with self.assertRaises(SiteGenericMethod):
         rlca = RegionalizationBase({("empty", "nothing"): 1},
                                    method=("a", "name"))
         rlca.get_ia_geocollections()
 def test_missing_intersection_error(self):
     empty = Database("empty")
     empty.register(depends=[], geocollections=["foo"])
     method = Method(("a", "name"))
     method.register(geocollections=["bar"])
     with self.assertRaises(MissingIntersection):
         rlca = RegionalizationBase({("empty", "nothing"): 1},
                                    method=("a", "name"))
         rlca.inventory_geocollections = rlca.get_inventory_geocollections()
         rlca.ia_geocollections = rlca.get_ia_geocollections()
         rlca.needed_intersections()
Esempio n. 11
0
    def create_methods(self):
        gw = [
            [("b", "bad"), 1],
        ]
        method = Method(("foo", ))
        method.register()
        method.write(gw)
        method.process()

        fake_dynamic_method = DynamicIAMethod("Dynamic foo")
        fake_dynamic_method.register()
        fake_dynamic_method.write({x[0]: x[1] for x in gw})
Esempio n. 12
0
def build_databases():
    Database("biosphere").write({
        ("biosphere", "1"): {'type': 'emission'},
        ("biosphere", "2"): {'type': 'emission'},
    })
    Database("test").write({
        ("test", "1"): {
            'exchanges': [{
                'amount': 0.5,
                'minimum': 0.2,
                'maximum': 0.8,
                'input': ('test', "2"),
                'type': 'technosphere',
                'uncertainty type': 4  # Uniform
            }, {
                'amount': 100,
                'minimum': 50,
                'maximum': 500,
                'input': ('biosphere', "1"),
                'type': 'biosphere',
                'loc': 100,
                'scale': 20,
                'uncertainty type': 3  # Normal
            }],
            'type': 'process',
        },
        ("test", "2"): {
            'exchanges': [{
                'amount': -0.42,
                'input': ('biosphere', "2"),
                'type': 'biosphere',
            }],
            'type': 'process',
            'unit': 'kg'
        },
    })
    method = Method(("a", "method"))
    method.register()
    method.write([
        (("biosphere", "1"), 1),
        (("biosphere", "2"), {
            'amount': 10,
            'uncertainty type': 5,  # Triangular
            'loc': 10,
            'minimum': 8,
            'maximum': 15
        }),
    ])
Esempio n. 13
0
def activity_and_method():
    database = DatabaseChooser("db")
    database.write({
        ("db", "a"): {
            "exchanges": [
                {
                    "input": ("db", "a"),
                    "amount": 2,
                    "type": "production",
                },
                {
                    "input": ("db", "b"),
                    "amount": 3,
                    "type": "technosphere",
                },
                {
                    "input": ("db", "c"),
                    "amount": 4,
                    "type": "biosphere",
                },
            ],
            "name":
            "a",
        },
        ("db", "b"): {
            "name": "b"
        },
        ("db", "c"): {
            "name": "c",
            "type": "biosphere"
        },
        ("db", "d"): {
            "name":
            "d",
            "exchanges": [{
                "input": ("db", "a"),
                "amount": 5,
                "type": "technosphere"
            }],
        },
    })
    cfs = [(("db", "c"), 42)]
    method = Method(("a method", ))
    method.register()
    method.write(cfs)
    return database.get("a"), method
Esempio n. 14
0
 def test_combine_methods(self):
     d = Database("biosphere")
     d.register(depends=[])
     d.write(biosphere)
     m1 = Method(("test method 1",))
     m1.register(unit="p")
     m1.write([(("biosphere", 1), 1, "GLO"), (("biosphere", 2), 2, "GLO")])
     m2 = Method(("test method 2",))
     m2.register(unit="p")
     m2.write([(("biosphere", 2), 10, "GLO")])
     combine_methods(("test method 3",), ("test method 1",), ("test method 2",))
     cm = Method(("test method 3",))
     self.assertEqual(
         sorted(cm.load()),
         [(("biosphere", 1), 1, "GLO"), (("biosphere", 2), 12, "GLO")],
     )
     self.assertEqual(methods[["test method 3"]]["unit"], "p")
Esempio n. 15
0
def build_databases():
    Database("biosphere").write({
        ("biosphere", "1"): {'type': 'emission'},
        ("biosphere", "2"): {'type': 'emission'},
    })
    Database("test").write({
        ("test", "1"): {
            'exchanges': [{
                'amount': 0.5,
                'minimum': 0.2,
                'maximum': 0.8,
                'input': ('test', "2"),
                'type': 'technosphere',
                'uncertainty type': 4
            }, {
                'amount': 1,
                'minimum': 0.5,
                'maximum': 1.5,
                'input': ('biosphere', "1"),
                'type': 'biosphere',
                'uncertainty type': 4
            }],
            'type': 'process',
        },
        ("test", "2"): {
            'exchanges': [{
                'amount': 0.1,
                'minimum': 0,
                'maximum': 0.2,
                'input': ('biosphere', "2"),
                'type': 'biosphere',
                'uncertainty type': 4
            }],
            'type': 'process',
            'unit': 'kg'
        },
    })
    method = Method(("a", "method"))
    method.register()
    method.write([
        (("biosphere", "1"), 1),
        (("biosphere", "2"), 2),
    ])
Esempio n. 16
0
    def to_worst_case_method(self,
                             name,
                             lower=None,
                             upper=None,
                             dynamic=True,
                             register=True):
        """Create a static LCA method using the worst case for each dynamic CF function.
        Default time interval over which to test for maximum CF is `datetime.now()` to `datetime.now()+relativedelta(years=100)`.
        
Args:
    * *name* (string): method name.
    * *lower* (datetime, default=datetime(2010, 1, 1): lower bound of the interval to consider.
    * *upper* (datetime, default=lower + relativedelta(years=100): upper bound of the interval to consider.
    * *dynamic* (bool, default=True): If total CF function of time of emission 
    * *register* (bool, default=True): If to register the method   

        """
        kwargs = {'dynamic': dynamic}
        if lower is not None:
            kwargs['lower'] = lower
        if upper is not None:
            kwargs['upper'] = upper
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            worst_case_method = Method(tuple(name))
            if worst_case_method.name not in methods:
                worst_case_method.register(dynamic_method=self.name)
        data = self.load()
        data.update(self.create_functions())
        # for now just characterize all the 'Carbon dioxide, in air' to be sure they are not skipped
        # should think better on how to deal with this
        method = [[('biosphere3', 'cc6a1abb-b123-4ca6-8f16-38209df609be'),
                   abs(get_maximum_value(value, **kwargs))]
                  if key == ('static_forest', "C_biogenic") else
                  [key, abs(get_maximum_value(value, **kwargs))]
                  for key, value in data.items()]
        #needed for GWP function to avoid registration every time
        if not register:
            return method
        worst_case_method.write(method)
        worst_case_method.process()  #GIU: guess not needed anymore right?
        return worst_case_method
Esempio n. 17
0
def add_method(add_biosphere):
    method = Method(("test method", ))
    method.register(unit="kg")
    method.write([(("biosphere", 1), 6, "foo"), (("biosphere", 2), 5, "bar")])
    def import_data(self):
        biosphere_data = {
            ('biosphere', 'F'): {
                'type': 'emission',
                'exchanges': [],
            },
            ('biosphere', 'G'): {
                'type': 'emission',
                'exchanges': [],
            }
        }
        biosphere = Database("biosphere")
        biosphere.register(depends=[], geocollections=[])
        biosphere.write(biosphere_data)

        inventory_data = {
            ('inventory', 'U'): {
                'type':
                'process',
                'location':
                "L",
                'exchanges': [
                    {
                        'input': ('biosphere', 'F'),
                        'type': 'biosphere',
                        'amount': 1
                    },
                    {
                        'input': ('biosphere', 'G'),
                        'type': 'biosphere',
                        'amount': 1
                    },
                ]
            },
            ('inventory', 'V'): {
                'type': 'process',
                'location': "M",
                'exchanges': []
            },
            ('inventory', 'X'): {
                'type': 'process',
                'location': "N",
                'exchanges': []
            },
            ('inventory', 'Y'): {
                'type': 'process',
                'location': "O",
                'exchanges': []
            },
            ('inventory', 'Z'): {
                'type': 'process',
                'location': "O",
                'exchanges': []
            }
        }
        inventory = Database("inventory")
        inventory.register(depends=["biosphere"], geocollections=["places"])
        inventory.write(inventory_data)

        intersection_data = [
            ["L", "A", 1],
            ["M", "A", 2],
            ["M", "B", 3],
            ["N", "B", 5],
            ["N", "C", 8],
            ["O", "C", 13],
        ]
        inter = Intersection(("places", "regions"))
        inter.register()
        inter.write(intersection_data)

        loading_data = [
            [2, "A"],
            [4, "B"],
            [8, "C"],
        ]
        loading = Loading("loading")
        loading.register()
        loading.write(loading_data)

        method_data = [
            [('biosphere', 'F'), 1, "A"],
            [('biosphere', 'G'), 2, "A"],
            [('biosphere', 'F'), 3, "B"],
            [('biosphere', 'G'), 4, "B"],
            [('biosphere', 'F'), 5, "C"],
            [('biosphere', 'G'), 6, "C"],
        ]
        method = Method(("a", "method"))
        method.register(geocollections=['regions'])
        method.write(method_data)
    def import_data(self):
        biosphere_data = {
            ('biosphere', 'F'): {
                'type': 'emission',
                'exchanges': [],
            },
            ('biosphere', 'G'): {
                'type': 'emission',
                'exchanges': [],
            }
        }
        biosphere = Database("biosphere")
        biosphere.register(depends=[], geocollections=[])
        biosphere.write(biosphere_data)

        inventory_data = {
            ('inventory', 'U'): {
                'type': 'process',
                'location': "L",
                'exchanges': [
                    {
                    'input': ('biosphere', 'F'),
                    'type': 'biosphere',
                    'amount': 1
                    },
                    {
                    'input': ('biosphere', 'G'),
                    'type': 'biosphere',
                    'amount': 1
                    },
                ]
            },
            ('inventory', 'V'): {
                'type': 'process',
                'location': "M",
                'exchanges': []
            },
            ('inventory', 'X'): {
                'type': 'process',
                'location': "N",
                'exchanges': []
            },
            ('inventory', 'Y'): {
                'type': 'process',
                'location': "O",
                'exchanges': []
            },
            ('inventory', 'Z'): {
                'type': 'process',
                'location': "O",
                'exchanges': []
            }
        }
        inventory = Database("inventory")
        inventory.register(depends=["biosphere"], geocollections=["places"])
        inventory.write(inventory_data)

        method_data = [
            [('biosphere', 'F'), 1, "L"],
            [('biosphere', 'G'), 2, "L"],
        ]
        method = Method(("a", "method"))
        method.register(geocollections=['places'])
        method.write(method_data)
def test_traverse_tagged_databases_graph_nonunitary_production():
    Database("biosphere").write(
        {
            ("biosphere", "bad"): {"name": "bad", "type": "emission"},
            ("biosphere", "worse"): {"name": "worse", "type": "emission"},
        }
    )
    method = Method(("test method",))
    method.register()
    method.write(
        [(("biosphere", "bad"), 2), (("biosphere", "worse"), 3),]
    )
    Database("background").write(
        {
            ("background", "first"): {
                "exchanges": [
                    {"input": ("biosphere", "bad"), "amount": 1, "type": "biosphere"},
                    {
                        "input": ("background", "first"),
                        "amount": 5,
                        "type": "production",
                    },
                ],
            },
            ("background", "second"): {
                "exchanges": [
                    {"input": ("biosphere", "worse"), "amount": 1, "type": "biosphere"}
                ],
            },
        }
    )
    Database("foreground").write(
        {
            ("foreground", "fu"): {
                "name": "functional unit",
                "tag field": "functional unit",
                "exchanges": [
                    {
                        "input": ("foreground", "i"),
                        "amount": 1,
                        "type": "technosphere",
                    },
                    {
                        "input": ("foreground", "iv"),
                        "amount": 4,
                        "type": "technosphere",
                    },
                    {"input": ("foreground", "fu"), "amount": 2, "type": "production",},
                ],
            },
            ("foreground", "i"): {
                "tag field": "A",
                "exchanges": [
                    {
                        "input": ("foreground", "ii"),
                        "amount": 2,
                        "type": "technosphere",
                    },
                    {
                        "input": ("foreground", "iii"),
                        "amount": 3,
                        "type": "technosphere",
                    },
                    {
                        "input": ("biosphere", "bad"),
                        "amount": 5,
                        "tag field": "C",
                        "type": "biosphere",
                    },
                    {
                        "input": ("biosphere", "worse"),
                        "amount": 6,
                        "type": "biosphere",
                    },
                ],
            },
            ("foreground", "ii"): {
                "tag field": "C",
                "exchanges": [
                    {"input": ("biosphere", "bad"), "amount": 8, "type": "biosphere",},
                    {
                        "input": ("biosphere", "worse"),
                        "amount": 7,
                        "tag field": "D",
                        "type": "biosphere",
                    },
                    {"input": ("foreground", "ii"), "amount": 3, "type": "production",},
                ],
            },
            ("foreground", "iii"): {
                # Default tag: "B"
                "exchanges": [
                    {
                        "input": ("background", "first"),
                        "amount": 10,
                        "type": "technosphere",
                    },
                    {
                        "input": ("biosphere", "bad"),
                        "tag field": "A",
                        "amount": 9,
                        "type": "biosphere",
                    },
                ],
            },
            ("foreground", "iv"): {
                "tag field": "C",
                "exchanges": [
                    {
                        "input": ("background", "second"),
                        "amount": 12,
                        "type": "technosphere",
                    },
                    {
                        "input": ("biosphere", "worse"),
                        "tag field": "B",
                        "amount": 11,
                        "type": "biosphere",
                    },
                    {
                        "input": ("foreground", "iv"),
                        "amount": 10,
                        "type": "production",
                    },
                ],
            },
        }
    )

    _, graph = traverse_tagged_databases(
        {("foreground", "fu"): 2}, ("test method",), label="tag field", default_tag="B"
    )
    expected = [
        {
            "amount": 2,
            "biosphere": [],
            "activity": get_activity(("foreground", "fu")),
            "technosphere": [
                {
                    "amount": 1,
                    "biosphere": [
                        {"amount": 5, "impact": 10, "tag": "C", "secondary_tags": []},
                        {"amount": 6, "impact": 18, "tag": "A", "secondary_tags": []},
                    ],
                    "activity": get_activity(("foreground", "i")),
                    "technosphere": [
                        {
                            "amount": 2,
                            "biosphere": [
                                {
                                    "amount": 16 / 3,
                                    "impact": 32 / 3,
                                    "tag": "C",
                                    "secondary_tags": [],
                                },
                                {
                                    "amount": 14 / 3,
                                    "impact": 42 / 3,
                                    "tag": "D",
                                    "secondary_tags": [],
                                },
                            ],
                            "activity": get_activity(("foreground", "ii")),
                            "technosphere": [],
                            "impact": 0,
                            "tag": "C",
                            "secondary_tags": [],
                        },
                        {
                            "amount": 3,
                            "biosphere": [
                                {
                                    "amount": 27,
                                    "impact": 54,
                                    "tag": "A",
                                    "secondary_tags": [],
                                }
                            ],
                            "activity": get_activity(("foreground", "iii")),
                            "technosphere": [],
                            "impact": 60 / 5,
                            "tag": "B",
                            "secondary_tags": [],
                        },
                    ],
                    "impact": 0,
                    "tag": "A",
                    "secondary_tags": [],
                },
                {
                    "amount": 4,
                    "biosphere": [
                        {
                            "amount": pytest.approx(44 / 10),
                            "impact": pytest.approx(132 / 10),
                            "tag": "B",
                            "secondary_tags": [],
                        }
                    ],
                    "activity": get_activity(("foreground", "iv")),
                    "technosphere": [],
                    "impact": pytest.approx(144 / 10),
                    "tag": "C",
                    "secondary_tags": [],
                },
            ],
            "impact": 0,
            "tag": "functional unit",
            "secondary_tags": [],
        }
    ]
    assert graph == expected
def tagged_fixture():

    Database("biosphere").write(
        {
            ("biosphere", "bad"): {"name": "bad", "type": "emission"},
            ("biosphere", "worse"): {"name": "worse", "type": "emission"},
        }
    )

    method = Method(("test method",))

    method.register()

    method.write(
        [(("biosphere", "bad"), 2), (("biosphere", "worse"), 3),]
    )

    Database("background").write(
        {
            ("background", "first"): {
                "exchanges": [
                    {"input": ("biosphere", "bad"), "amount": 1, "type": "biosphere",}
                ],
            },
            ("background", "second"): {
                "exchanges": [
                    {"input": ("biosphere", "worse"), "amount": 1, "type": "biosphere",}
                ],
            },
        }
    )

    Database("foreground").write(
        {
            ("foreground", "fu"): {
                "name": "functional unit",
                "tag field": "functional unit",
                "secondary tag": "X",
                "exchanges": [
                    {
                        "input": ("foreground", "i"),
                        "amount": 1,
                        "type": "technosphere",
                    },
                    {
                        "input": ("foreground", "iv"),
                        "amount": 4,
                        "type": "technosphere",
                    },
                ],
            },
            ("foreground", "i"): {
                "tag field": "A",
                "secondary tag": "X",
                "exchanges": [
                    {
                        "input": ("foreground", "ii"),
                        "amount": 2,
                        "type": "technosphere",
                    },
                    {
                        "input": ("foreground", "iii"),
                        "amount": 3,
                        "type": "technosphere",
                    },
                    {
                        "input": ("biosphere", "bad"),
                        "amount": 5,
                        "tag field": "C",
                        "type": "biosphere",
                    },
                    {
                        "input": ("biosphere", "worse"),
                        "amount": 6,
                        "type": "biosphere",
                    },
                ],
            },
            ("foreground", "ii"): {
                "tag field": "C",
                "secondary tag": "X",
                "exchanges": [
                    {"input": ("biosphere", "bad"), "amount": 8, "type": "biosphere",},
                    {
                        "input": ("biosphere", "worse"),
                        "amount": 7,
                        "tag field": "D",
                        "secondary tag": "Y",
                        "type": "biosphere",
                    },
                ],
            },
            ("foreground", "iii"): {
                # Default tag: "B"
                # Default secondary tag: "unknown"
                "exchanges": [
                    {
                        "input": ("background", "first"),
                        "amount": 10,
                        "type": "technosphere",
                    },
                    {
                        "input": ("biosphere", "bad"),
                        "tag field": "A",
                        "secondary tag": "Y",
                        "amount": 9,
                        "type": "biosphere",
                    },
                ],
            },
            ("foreground", "iv"): {
                "tag field": "C",
                "secondary tag": "Y",
                "exchanges": [
                    {
                        "input": ("background", "second"),
                        "amount": 12,
                        "type": "technosphere",
                    },
                    {
                        "input": ("biosphere", "worse"),
                        "tag field": "B",
                        "secondary tag": "Y",
                        "amount": 11,
                        "type": "biosphere",
                    },
                ],
            },
        }
    )