def test_write_only_activity_parameters_no_activate_others(no_init):
    Database("PCB").register()
    obj = ExcelImporter()
    obj.db_name = "PCB"
    obj.data = deepcopy(DATA)
    obj.write_database(activate_parameters=False)

    NEW = [{
        'code':
        '45cb34db4147e510a2561cceec541f6b',
        'database':
        'PCB',
        'exchanges': [],
        'name':
        'unmounted printed circuit board',
        'type':
        'process',
        'unit':
        'square meter',
        'parameters': [{
            'name': 'something_test',
            'amount': 2,
            'formula': '3 + 2'
        }],
    }]
    obj = ExcelImporter()
    obj.db_name = "PCB"
    obj.write_activity_parameters(NEW)

    assert ActivityParameter.select().count() == 1
    assert ActivityParameter.get().formula == '3 + 2'
    assert 'parameters' not in get_activity(
        ('PCB', '45cb34db4147e510a2561cceec541f6b'))
    assert 'parameters' in get_activity(
        ('PCB', '32aa5ab78beda5b8c8efbc89587de7a5'))
Beispiel #2
0
def test_compare_activities_by_grouped_leaves_html(cabgl):
    result = compare_activities_by_grouped_leaves(
        [bd.get_activity(("c", "6")), bd.get_activity(("c", "7"))],
        ("method",),
        output_format="html",
    )
    assert isinstance(result, str)
Beispiel #3
0
def test_compare_activities_by_grouped_leaves_pandas(cabgl):
    result = compare_activities_by_grouped_leaves(
        [bd.get_activity(("c", "6")), bd.get_activity(("c", "7"))],
        ("method",),
        output_format="pandas",
    )
    assert isinstance(result, pd.DataFrame)
Beispiel #4
0
def test_find_differences_in_inputs(fdii):
    expected = {
        bd.get_activity(("c", "3")): {"flow": 1},
        bd.get_activity(("c", "4")): {"flow": 1.1},
        bd.get_activity(("c", "5")): {"flow": 0.95},
    }
    assert find_differences_in_inputs(bd.get_activity(("c", "3"))) == expected
Beispiel #5
0
def test_compare_activities_by_grouped_leaves(cabgl):
    labels, result = compare_activities_by_grouped_leaves(
        [bd.get_activity(("c", "6")), bd.get_activity(("c", "7"))], ("method",)
    )
    assert labels == [
        "activity",
        "product",
        "location",
        "unit",
        "total",
        "direct emissions",
        "product A",
        "product B",
        "product C",
        "product D",
    ]
    assert result[0][0] == "6"
    assert result[1][0] == "7"
    assert np.allclose(
        result[0][4:],
        [251, 6 / 251, (27 + 35 + 56) / 251, 56 / 251, 36 / 251, 35 / 251],
    )
    assert np.allclose(
        result[1][4:], [212, 0, (30 + 48 + 24) / 212, 48 / 212, 32 / 212, 30 / 212]
    )
Beispiel #6
0
    def to_dataframe(self, cutoff=200):
        """Return all nonzero elements of characterized inventory as Pandas dataframe"""
        assert mapping, "This method doesn't work with independent LCAs"
        assert pandas, "This method requires the `pandas` (http://pandas.pydata.org/) library"
        assert hasattr(
            self, "characterized_inventory"), "Must do LCIA calculation first"

        from bw2data import get_activity

        coo = self.characterized_inventory.tocoo()
        stacked = np.vstack([np.abs(coo.data), coo.row, coo.col, coo.data])
        stacked.sort()
        rev_activity, _, rev_bio = self.reverse_dict()
        length = stacked.shape[1]

        data = []
        for x in range(min(cutoff, length)):
            if stacked[3, length - x - 1] == 0.:
                continue
            activity = get_activity(rev_activity[stacked[2, length - x - 1]])
            flow = get_activity(rev_bio[stacked[1, length - x - 1]])
            data.append((activity['name'], flow['name'],
                         activity.get('location'), stacked[3, length - x - 1]))
        return pandas.DataFrame(
            data, columns=['Activity', 'Flow', 'Region', 'Amount'])
def test_write_only_activity_parameters_no_activate_others(no_init):
    Database("PCB").register()
    obj = ExcelImporter()
    obj.db_name = "PCB"
    obj.data = deepcopy(DATA)
    obj.write_database(activate_parameters=False)

    NEW = [
        {
            "code": "45cb34db4147e510a2561cceec541f6b",
            "database": "PCB",
            "exchanges": [],
            "name": "unmounted printed circuit board",
            "type": "process",
            "unit": "square meter",
            "parameters": [{"name": "something_test", "amount": 2, "formula": "3 + 2"}],
        }
    ]
    obj = ExcelImporter()
    obj.db_name = "PCB"
    obj.write_activity_parameters(NEW)

    assert ActivityParameter.select().count() == 1
    assert ActivityParameter.get().formula == "3 + 2"
    assert "parameters" not in get_activity(("PCB", "45cb34db4147e510a2561cceec541f6b"))
    assert "parameters" in get_activity(("PCB", "32aa5ab78beda5b8c8efbc89587de7a5"))
Beispiel #8
0
def test_locations_changed_as_expected(basic):
    rower = Rower("animals")
    rower.define_RoWs()
    rower.label_RoWs()
    assert get_activity(('animals', 'mutt pup'))['location'] == 'RoW_user_0'
    assert get_activity(('animals', 'mutt'))['location'] == 'RoW_user_0'
    assert get_activity(('animals', 'moggy'))['location'] == 'RoW_user_1'
Beispiel #9
0
def test_find_differences_in_inputs_locations(fdii):
    expected = {
        bd.get_activity(("c", "3")): {"flow": 1},
        bd.get_activity(("c", "4")): {"flow": 1.1},
    }
    assert (
        find_differences_in_inputs(bd.get_activity(("c", "3")), locations=["here"])
        == expected
    )
    def append_one_exchange(cls, df, df_ind_j, conversion_dem_to_fu, exclude_dbs):
        """Extract info about one input activity, eg name, unit, location, etc and append it to the dataframe df."""

        # Extract the activity number
        k = int(''.join(c for c in df_ind_j.index[0] if c.isdigit()))
        # Extract information about activity and save it
        original_str = df_ind_j['DB Act {}'.format(k)]
        original_db_code = df_ind_j['Activity {}'.format(k)]

        # Find this input activity in brightway databases
        db_name = original_db_code.split("'")[1]
        code = original_db_code.split("'")[3]
        original_db_code_tuple = (db_name, code)

        # exclude unnecessary databases
        if db_name.lower() in exclude_dbs:
            return df

        # Compute amount
        original_on = df_ind_j['On ' + str(k)]
        original_amount = df_ind_j['Amount Act ' + str(k)]
        original_cfl = df_ind_j['CFL Act ' + str(k)]
        computed_amount = original_on \
                          * original_amount \
                          * original_cfl \
                          * conversion_dem_to_fu

        if db_name == 'ecoinvent 3.3 cutoff' and 'ecoinvent 3.3 cutoff' not in bd.databases:
            current_project = deepcopy(bd.projects.current)
            bd.projects.set_current('ecoinvent 3.3 cutoff')  # Temporarily switch to ecoinvent 3.3 project
            act_bw = bd.get_activity(original_db_code_tuple)
            bd.projects.set_current(current_project)
            input_act_values_dict = cls.create_input_act_dict(act_bw, computed_amount)
        else:
            try:
                # Find activity using bw functionality
                act_bw = bd.get_activity(original_db_code_tuple)
                input_act_values_dict = cls.create_input_act_dict(act_bw, computed_amount)
            except:
                # If bd.get_activity does not work for whichever reason, fill info manually
                # if replace_agribalyse_with_ei and "agribalyse" in db_name.lower():
                #     db_name = CONSUMPTION_DB_NAME TODO might need to uncomment, or fix this somewhere
                input_act_values_dict = cls.bw_get_activity_info_manually(original_str, db_name, computed_amount)

        # Add exchange to the dataframe with database in brightway format
        input_act_values_dict.update(
            {
                'original_on': original_on,
                'original_activity': original_db_code,
                'original_db_act': original_str,
                'original_cfl_act': original_cfl,
                'original_amount': original_amount,
            }
        )
        df = cls.append_exchanges_in_correct_columns(df, input_act_values_dict)

        return df
Beispiel #11
0
def test_find_differences_in_inputs_tolerances(fdii):
    assert not find_differences_in_inputs(bd.get_activity(("c", "3")), rel_tol=0.2)

    expected = {
        bd.get_activity(("c", "3")): {"flow": 1},
        bd.get_activity(("c", "4")): {"flow": 1.1},
    }
    assert (
        find_differences_in_inputs(bd.get_activity(("c", "3")), abs_tol=0.075)
        == expected
    )
Beispiel #12
0
 def _add_results(self, res_dict, key, imp):
     """used in charachterize by flow and processes to groupby impact by year for each flow"""
     if get_activity(key)['name'] not in res_dict:
         #just add to dict
         res_dict[get_activity(key)['name']] = imp
     else:
         #groupby and sum impact by year
         imp[0].extend(res_dict[get_activity(key)['name']][0])
         imp[1].extend(res_dict[get_activity(key)['name']][1])
         c = collections.defaultdict(int)
         for yr, im in zip(imp[0], imp[1]):
             c[yr] += im
         res_dict[get_activity(key)['name']] = tuple(
             list(t) for t in zip(*sorted(zip(c.keys(), c.values())))
         )  #from https://stackoverflow.com/a/9764364/4929813
Beispiel #13
0
def test_with_ecoinvent_generic():
    assert not len(Database('animals'))
    animal_data = {
        ('animals', 'dogo'): {
            'name': 'dogs',
            'reference product': 'dog',
            'exchanges': [],
            'unit': 'kilogram',
            'location': 'BR',
        },
        ('animals', 'st bernhard'): {
            'name': 'dogs',
            'reference product': 'dog',
            'exchanges': [],
            'unit': 'kilogram',
            'location': 'CH',
        },
        ('animals', 'mutt'): {
            'name': 'dogs',
            'reference product': 'dog',
            'exchanges': [],
            'unit': 'kilogram',
            'location': 'RoW',
        },
    }
    db = Database('animals')
    db.write(animal_data)

    rwr = rower.Rower('animals')
    rwr.load_existing(rwr.EI_GENERIC)
    rwr.define_RoWs()
    rwr.label_RoWs()
    assert get_activity(('animals', 'mutt'))['location'] == "RoW_88"
Beispiel #14
0
 def _update_locations_sqlite(self, mapping):
     count = 0
     for k, v in pyprind.prog_bar(mapping.items()):
         activity = bw2data.get_activity((self.db.name, k))
         activity['location'] = v
         activity.save()
         count += 1
     return count
 def compute_exiobase_weights(self):
     reverse_dict = self.lca.reverse_dict()[0]
     act_inds = np.where(self.d_exiobase_adjusted != 0)[0]
     weights = {}
     for act in act_inds:
         bw_act = bd.get_activity(reverse_dict[act]).as_dict()['key']
         weights[bw_act] = self.d_exiobase_adjusted[act]
     return weights
Beispiel #16
0
 def compare_to_previous(self):
     if not hasattr(self, "previous_reference"):
         raise ValueError("No previous reference method found")
     names_found_in_data = {
         get_activity(cf["input"])["name"].lower()
         for ds in self.data for cf in ds["exchanges"] if cf.get("input")
     }
     names_missing_in_data = {
         cf["name"].lower()
         for ds in self.data for cf in ds["exchanges"]
         if not cf.get("input")
     }
     names_in_reference = {
         get_activity(key)["name"].lower()
         for key, _ in Method(self.previous_reference).load()
     }
     return {
         "found": names_found_in_data,
         "missing": names_missing_in_data,
         "reference": names_in_reference,
     }
Beispiel #17
0
def test_compare_activities_by_grouped_leaves_max_level(cabgl):
    labels, result = compare_activities_by_grouped_leaves(
        [bd.get_activity(("c", "6")), bd.get_activity(("c", "7"))],
        ("method",),
        max_level=1,
    )
    assert labels == [
        "activity",
        "product",
        "location",
        "unit",
        "total",
        "direct emissions",
        "product D",
        "product C",
    ]
    assert result[0][0] == "6"
    assert result[1][0] == "7"
    assert np.allclose(
        result[0][4:], [251, 6 / 251, (35 + 35 + 56 + 56) / 251, (36 + 27) / 251]
    )
Beispiel #18
0
    def annotated_top_emissions(self, lca, names=True, **kwargs):
        """Get list of most damaging biosphere flows in an LCA, sorted by ``abs(direct impact)``.

        Returns a list of tuples: ``(lca score, inventory amount, activity)``. If ``names`` is False, they returns the process key as the last element.

        """
        ra, rp, rb = lca.reverse_dict()
        results = [(score, lca.inventory[index, :].sum(), rb[index])
                   for score, index in self.top_emissions(
                       lca.characterized_inventory, **kwargs)]
        if names:
            results = [(x[0], x[1], get_activity(x[2])) for x in results]
        return results
Beispiel #19
0
    def annotated_top_processes(self, lca, names=True, **kwargs):
        """Get list of most damaging processes in an LCA, sorted by ``abs(direct impact)``.

        Returns a list of tuples: ``(lca score, supply, activity)``. If ``names`` is False, they returns the process key as the last element.

        """
        ra, rp, rb = lca.reverse_dict()
        results = [(score, lca.supply_array[int(index)], ra[int(index)])
                   for score, index in self.top_processes(
                       lca.characterized_inventory, **kwargs)]
        if names:
            results = [(x[0], x[1], get_activity(x[2])) for x in results]
        return results
def fix_acrolein():
    ERROR = "ReCiPe 2016 only tested for ecoinvent biosphere flows; install base ecoinvent data"
    assert "biosphere3" in bd.databases, ERROR

    bio = bd.Database("biosphere3")
    if bio.metadata.get("acrolein fixed"):
        return

    flow = bd.get_activity(
        ("biosphere3", "fa8bd05b-015d-5a82-878c-bde991551695"))
    flow["CAS number"] = "107-02-8"
    flow.save()

    bio.metadata["acrolein fixed"] = True
    bd.databases.flush()
Beispiel #21
0
def test_compare_activities_by_grouped_leaves_max_cutoff(cabgl):
    labels, result = compare_activities_by_grouped_leaves(
        [bd.get_activity(("c", "6")), bd.get_activity(("c", "7"))],
        ("method",),
        cutoff=0.2,
    )
    assert labels == [
        "activity",
        "product",
        "location",
        "unit",
        "total",
        "direct emissions",
        "product B",
        "product A",
        "product C",
        "product D",
    ]
    assert result[0][0] == "6"
    assert result[1][0] == "7"
    assert np.allclose(
        result[0][4:],
        [251, 6 / 251, (56 + 27 + 35) / 251, (56) / 251, 36 / 251, 35 / 251],
    )
    def calculate(self):
        """Calculate LCA report data"""
        lca = LCA(self.activity, self.method)
        lca.lci()
        lca.lcia()

        gt = GraphTraversal().calculate(self.activity, method=self.method)
        print("FD")
        force_directed = self.get_force_directed(gt["nodes"], gt["edges"], lca)
        print("CA")
        ca = ContributionAnalysis()
        print("hinton")
        hinton = ca.hinton_matrix(lca)
        print("treemap")
        treemap = self.get_treemap(gt["nodes"], gt["edges"], lca)
        print("herfindahl")
        herfindahl = herfindahl_index(lca.characterized_inventory.data)
        print("concentration")
        concentration = concentration_ratio(lca.characterized_inventory.data)
        print("MC:")
        monte_carlo = self.get_monte_carlo()

        activity_data = []
        for k, v in self.activity.items():
            obj = get_activity(k)
            activity_data.append((obj["name"], "%.2g" % v, obj["unit"]))

        self.report = {
            "activity": activity_data,
            "method": {
                "name": ": ".join(self.method),
                "unit": methods[self.method]["unit"],
            },
            "score": float(lca.score),
            "contribution": {
                "hinton": hinton,
                "treemap": treemap,
                "herfindahl": herfindahl,
                "concentration": concentration,
            },
            "force_directed": force_directed,
            "monte carlo": monte_carlo,
            "metadata": {
                "type": "Brightway2 serialized LCA report",
                "version": self.version,
                "uuid": self.uuid,
            },
        }
Beispiel #23
0
    def patch_lcia_methods(self, new_biosphere):
        flows = ["PFC (CO2-eq)", "HFC (CO2-eq)"]

        for flow in flows:
            assert get_activity((new_biosphere, flow))

        new_data = [((new_biosphere, flow), 1) for flow in flows]
        count = 0

        for name, metadata in methods.items():
            if metadata.get("unit") == "kg CO2-Eq":
                count += 1
                obj = Method(name)
                data = obj.load()
                data.extend(new_data)
                obj.write(data)

        print(f"Patched {count} LCIA methods with unit 'kg CO2-Eq'")
Beispiel #24
0
def test_with_ecoinvent_specific_shortcut():
    assert not len(Database('animals'))
    animal_data = {
        ('animals', "6ccf7e69afcf1b74de5b52ae28bbc1c2"): {
            'name': 'dogs',
            'reference product': 'dog',
            'exchanges': [],
            'unit': 'kilogram',
            'location': 'RoW',
        },
    }
    db = Database('animals')
    db.write(animal_data)

    rwr = rower.Rower('animals')
    rwr.apply_existing_activity_map(rwr.EI_3_4_CONSEQUENTIAL)
    assert get_activity(
        ('animals',
         "6ccf7e69afcf1b74de5b52ae28bbc1c2"))['location'] == "RoW_64"
Beispiel #25
0
def multi_recurse_tagged_database(activity, amount, methods, method_dicts, lca, label, default_tag, secondary_tags=[]):
   
    if isinstance(activity, tuple):
        activity = get_activity(activity)

    inputs = list(activity.technosphere())
    inside = [exc for exc in inputs
              if exc['input'][0] == activity['database']]
    outside = {exc['input']: exc['amount'] * amount
               for exc in inputs
               if exc['input'][0] != activity['database']}

    if outside:
        outside_scores = []
        for n, m in enumerate(methods):
            lca.switch_method(m)
            lca.redo_lcia(outside)
            outside_scores.append(lca.score)
    else:
        outside_scores = [0] * len(methods)
        
    return {
        'activity': activity,
        'amount': amount,
        'tag': activity.get(label) or default_tag,
        'secondary_tags':[activity.get(t[0]) or t[1] for t in secondary_tags],
        'impact': outside_scores,
        'biosphere': [{
            'amount': exc['amount'] * amount,
            'impact': [exc['amount'] * amount * method_dict.get(exc['input'], 0) for method_dict in method_dicts],
            'tag': exc.get(label) or activity.get(label) or default_tag,
            'secondary_tags':[exc.get(t[0]) or activity.get(t[0]) or t[1] for t in secondary_tags]
        } for exc in activity.biosphere()],
        'technosphere': [multi_recurse_tagged_database(exc.input, exc['amount'] * amount, methods,
                                                 method_dicts, lca, label, default_tag, secondary_tags)
                         for exc in inside]
    }
Beispiel #26
0
def multi_recurse_tagged_database(activity,
                                  amount,
                                  methods,
                                  method_dicts,
                                  lca,
                                  label,
                                  default_tag,
                                  secondary_tags=[]):
    """Traverse a foreground database and assess activities and biosphere flows by tags using multiple methods.

    Input arguments:

        * ``activity``: Activity tuple or object
        * ``amount``: float
        * ``methods``: list of LCA methods (tuples)
        * ``method_dicts``: list of dictionaries of biosphere flow tuples to CFs, e.g. ``{("biosphere", "foo"): 3}`` corresponding to methods in ``methods``
        * ``lca``: An ``LCA`` object that is already initialized, i.e. has already calculated LCI
        * ``label``: string
        * ``default_tag``: string
        * ``secondary_tags``: list of tuples in the format (secondary_label, secondary_default_tag). Default is empty list.

    Returns:

    .. code-block:: python

        {
            'activity': activity object,
            'amount': float,
            'tag': string,
            'secondary_tags': [list of strings],
            'impact': [list of floats (impact of inputs from outside foreground database) with one element per method],
            'biosphere': [{
                'amount': float,
                'impact': [list of floats with one element per method],
                'tag': string,
                'secondary_tags': [list of strings]
            }],
            'technosphere': [this data structure]
        }

    """

    if isinstance(activity, tuple):
        activity = get_activity(activity)

    inputs = list(activity.technosphere())
    inside = [exc for exc in inputs if exc["input"][0] == activity["database"]]
    outside = {
        exc["input"]: exc["amount"] * amount
        for exc in inputs if exc["input"][0] != activity["database"]
    }

    if outside:
        outside_scores = []
        for n, m in enumerate(methods):
            lca.switch_method(m)
            lca.redo_lcia(outside)
            outside_scores.append(lca.score)
    else:
        outside_scores = [0] * len(methods)

    return {
        "activity":
        activity,
        "amount":
        amount,
        "tag":
        activity.get(label) or default_tag,
        "secondary_tags": [activity.get(t[0]) or t[1] for t in secondary_tags],
        "impact":
        outside_scores,
        "biosphere": [{
            "amount":
            exc["amount"] * amount,
            "impact": [
                exc["amount"] * amount * method_dict.get(exc["input"], 0)
                for method_dict in method_dicts
            ],
            "tag":
            exc.get(label) or activity.get(label) or default_tag,
            "secondary_tags": [
                exc.get(t[0]) or activity.get(t[0]) or t[1]
                for t in secondary_tags
            ],
        } for exc in activity.biosphere()],
        "technosphere": [
            multi_recurse_tagged_database(
                exc.input,
                exc["amount"] * amount,
                methods,
                method_dicts,
                lca,
                label,
                default_tag,
                secondary_tags,
            ) for exc in inside
        ],
    }
Beispiel #27
0
def recurse_tagged_database(activity,
                            amount,
                            method_dict,
                            lca,
                            label,
                            default_tag,
                            secondary_tags=[]):
    """Traverse a foreground database and assess activities and biosphere flows by tags.


    Input arguments:


        * ``activity``: Activity tuple or object

        * ``amount``: float

        * ``method_dict``: Dictionary of biosphere flow tuples to CFs, e.g. ``{("biosphere", "foo"): 3}``

        * ``lca``: An ``LCA`` object that is already initialized, i.e. has already calculated LCI and LCIA with same method as in ``method_dict``

        * ``label``: string

        * ``default_tag``: string

        * ``secondary_tags``: List of tuples in the format (secondary_label, secondary_default_tag). Default is empty list.


    Returns:


    .. code-block:: python


        {

            'activity': activity object,

            'amount': float,

            'tag': string,

            'secondary_tags': [list of strings],

            'impact': float (impact of inputs from outside foreground database),

            'biosphere': [{

                'amount': float,

                'impact': float,

                'tag': string,

                'secondary_tags': [list of strings]

            }],

            'technosphere': [this data structure]

        }


    """

    if isinstance(activity, tuple):

        activity = get_activity(activity)

    inputs = list(activity.technosphere())

    production = list(activity.production())
    if len(production) == 1:
        scale = production[0]["amount"]
    elif not production:
        # Assume production amount of 1
        scale = 1
    else:
        raise ValueError("Can't scale by production exchange")

    inside = [exc for exc in inputs if exc["input"][0] == activity["database"]]

    outside = {
        exc["input"]: exc["amount"] / scale * amount
        for exc in inputs if exc["input"][0] != activity["database"]
    }

    if outside:

        lca.redo_lcia(outside)

        outside_score = lca.score

    else:

        outside_score = 0

    return {
        "activity":
        activity,
        "amount":
        amount,
        "tag":
        activity.get(label) or default_tag,
        "secondary_tags": [activity.get(t[0]) or t[1] for t in secondary_tags],
        "impact":
        outside_score,
        "biosphere": [{
            "amount":
            exc["amount"] / scale * amount,
            "impact":
            exc["amount"] / scale * amount * method_dict.get(exc["input"], 0),
            "tag":
            exc.get(label) or activity.get(label) or default_tag,
            "secondary_tags": [
                exc.get(t[0]) or activity.get(t[0]) or t[1]
                for t in secondary_tags
            ],
        } for exc in activity.biosphere()],
        "technosphere": [
            recurse_tagged_database(
                exc.input,
                exc["amount"] / scale * amount,
                method_dict,
                lca,
                label,
                default_tag,
                secondary_tags,
            ) for exc in inside
        ],
    }
Beispiel #28
0
 def get_name(self, key):
     return get_activity(key).get("name", "Unknown")
Beispiel #29
0
def test_calculate_matrix_presamples():
    data = {
        ("test-db", 'b'): {
            'exchanges': [],
            'type': 'emission',
        },
        ("test-db", 't1'): {
            'exchanges': [{
                'amount': 1,
                'input': ('test-db', 't2'),
                'type': 'technosphere',
                'formula': 'foo + bar'
            }, {
                'amount': 1,
                'input': ('test-db', 'b'),
                'type': 'biosphere',
                'formula': 'foo - bar + pppp'
            }],
            'type':
            'process',
        },
        ("test-db", 't2'): {
            'exchanges': [],
            'type': 'process',
        },
    }
    Database("test-db").write(data)
    Group.create(name="E", order=[])
    data = [{
        'name': 'foo',
        'database': 'test-db',
        'code': 't1',
        'amount': 7,
        'uncertainty_type': 4,
        'minimum': 0,
        'maximum': 14,
    }, {
        'name': 'bar',
        'database': 'test-db',
        'code': 't1',
        'amount': 11,
    }]
    parameters.new_project_parameters([{'name': 'pppp', 'amount': 12}])
    parameters.new_activity_parameters(data, 'A')
    parameters.add_exchanges_to_group('A', get_activity(("test-db", 't1')))
    parameters.recalculate()

    pbm = ParameterizedBrightwayModel("A")
    pbm.load_parameter_data()
    pbm.calculate_static()
    pbm.calculate_matrix_presamples()
    id_, dirpath = pbm.save_presample('test-everything')

    # Check for file contents
    pp = PresamplesPackage(dirpath)
    resources = pp.resources
    assert len(resources) == 3
    assert resources[0]['type'] == 'biosphere'
    assert resources[0]['samples']['shape'] == [1, 1]
    assert resources[1]['type'] == 'technosphere'
    assert resources[1]['samples']['shape'] == [1, 1]
    assert resources[2]['label'] == 'test-everything'
    assert resources[2]['samples']['shape'] == [3, 1]
def test_upstream_bio(activity):
    act = get_activity(("db", "c"))
    assert len(list(act.upstream())) == 0
    assert len(act.upstream()) == 0