def test_append_package(): ProjectParameter.create( name="p1", amount=1, ) ProjectParameter.create( name="p2", amount=1, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("project") pbm.load_parameter_data() pbm.calculate_static() for obj in pbm.data.values(): obj['amount'] = 10 _, dirpath = pbm.save_presample('project-test') pp = PresamplesPackage(dirpath) assert len(pp) == 1 assert pp.parameters['project__p1'] == 10 Database("db").register() Group.create(name="D", order=[]) DatabaseParameter.create( database="db", name="db1", formula="2 * p1", amount=2, ) DatabaseParameter.create( database="db", name="db2", amount=2, ) ActivityParameter.create( group="D", database="db", code="D1", name="d1", formula="p1 + db1", amount=3, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("D") pbm.load_existing(dirpath) expected = {'project__p1': 10, 'project__p2': 10} assert pbm.global_params == expected pbm.load_parameter_data() pbm.data = {'D__d1': pbm.data['D__d1']} pbm.data['D__d1']['amount'] = 12 _, dp = pbm.append_presample(dirpath, 'D-test') assert dp == dirpath pp = PresamplesPackage(dirpath) assert len(pp) == 2 assert pp.parameters['D__d1'] == 12 assert pp.parameters['project__p1'] == 10
def test_calculate_stochastic(): Database("db").register() ProjectParameter.create( name="p1", amount=1, ) ProjectParameter.create( name="p2", amount=1, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("project") pbm.load_parameter_data() pbm.data['project__p1']['amount'] = np.ones(10) + 100 pbm.data['project__p2']['amount'] = np.ones(10) + 10 _, dirpath_project = pbm.save_presample('project-test') pp = PresamplesPackage(dirpath_project) assert len(pp) == 1 assert np.allclose(pp.parameters['project__p1'], np.ones(10) + 100) # Create rest of parameters Group.create(name="E", order=[]) ActivityParameter.create( group="E", database="db", code="E1", name="e1", formula="p1 + p2 + e2", amount=4, ) ActivityParameter.create(group="E", database="db", code="E2", name="e2", amount=1, data={ 'uncertainty type': 4, 'minimum': 1000, 'maximum': 1100 }) parameters.recalculate() pbm = ParameterizedBrightwayModel("E") pbm.load_existing(dirpath_project) pbm.load_parameter_data() result = pbm.calculate_stochastic(10) assert np.allclose(result['project__p1'], [101] * 10) assert np.allclose(result['project__p2'], [11] * 10) assert all(result['E__e2'] >= 1000) assert all(result['E__e2'] <= 1100) assert np.allclose(result['E__e1'], result['E__e2'] + 101 + 11)
def test_graph_rebuild(qtbot, bw2test): """Test that the graph is correctly built and rebuilt, ensure that the 'finish' button is enabled and disabled at the correct times. """ param = ProjectParameter.create(name="test1", amount=3) wizard = UncertaintyWizard(param, None) qtbot.addWidget(wizard) wizard.show() # Check that the graph exists and distribution is 'unknown' assert wizard.type.plot.isVisible() assert wizard.type.distribution.currentIndex() == UndefinedUncertainty.id assert wizard.button(QWizard.FinishButton).isEnabled() # Select an uncertainty distribution, fill out numbers. with qtbot.waitSignal(wizard.type.distribution.currentIndexChanged, timeout=100): wizard.type.distribution.setCurrentIndex(UniformUncertainty.id) assert not wizard.type.complete # Missing values for valid uncertainty. assert not wizard.button(QWizard.FinishButton).isEnabled() # When programmatically changing values, no textEdited signal is emitted. with qtbot.assertNotEmitted(wizard.type.minimum.textEdited): wizard.type.minimum.setText("1") wizard.type.generate_plot() assert not wizard.type.complete # Still missing 'maximum' assert not wizard.button(QWizard.FinishButton).isEnabled() with qtbot.assertNotEmitted(wizard.type.minimum.textEdited): wizard.type.maximum.setText("5") wizard.type.generate_plot() assert wizard.type.complete assert wizard.button(QWizard.FinishButton).isEnabled()
def test_lognormal_mean_balance(qtbot, bw2test): uncertain = { "loc": 2, "scale": 0.2, "uncertainty type": 2, } param = ProjectParameter.create(name="uc1", amount=3, data=uncertain) wizard = UncertaintyWizard(param, None) qtbot.addWidget(wizard) wizard.show() # Compare loc with mean, loc, mean = float(wizard.type.loc.text()), float(wizard.type.mean.text()) assert np.isclose(np.exp(loc), mean) wizard.type.check_negative() assert not wizard.field("negative") # Alter mean and loc fields in turn to show balancing methods with qtbot.assertNotEmitted(wizard.type.mean.textEdited): wizard.type.mean.setText("") wizard.type.balance_loc_with_mean() wizard.type.check_negative() assert wizard.type.loc.text() == "nan" # Setting the mean to a negative number will still return the same loc # value, but it will alter the 'negative' field. with qtbot.assertNotEmitted(wizard.type.mean.textEdited): wizard.type.mean.setText("-5") wizard.type.balance_loc_with_mean() wizard.type.check_negative() assert np.isclose(np.exp(float(wizard.type.loc.text())), 5) assert wizard.field("negative")
def test_update_alter_mean(qtbot, monkeypatch, ab_app): param = ProjectParameter.create(name="uc2", amount=1) wizard = UncertaintyWizard(param, None) qtbot.addWidget(wizard) wizard.show() # Select the lognormal distribution and set 'loc' and 'scale' fields. wizard.type.distribution.setCurrentIndex(LognormalUncertainty.id) wizard.type.loc.setText("1") wizard.type.scale.setText("0.3") wizard.type.generate_plot() assert wizard.type.complete # Now, monkeypatch Qt to ensure a 'yes' is selected for updating. monkeypatch.setattr(QMessageBox, "question", staticmethod(lambda *args: QMessageBox.Yes)) # Now trigger a 'finish' action with qtbot.waitSignal(signals.parameters_changed, timeout=100): wizard.button(QWizard.FinishButton).click() # Reload param and check that the amount is changed. param = ProjectParameter.get(name="uc2") assert "loc" in param.data and param.amount != 1 loc = param.data["loc"] assert loc == 1 assert np.isclose(np.log(param.amount), loc)
def test_pedigree(qtbot, bw2test): """Configure uncertainty using the pedigree page of the wizard.""" uncertain = { "loc": 2, "scale": 0.2, "uncertainty type": 2, "pedigree": { "reliability": 1, "completeness": 2, "temporal correlation": 2, "geographical correlation": 2, "further technological correlation": 3 }, } param = ProjectParameter.create(name="uc1", amount=3, data=uncertain) wizard = UncertaintyWizard(param, None) qtbot.addWidget(wizard) wizard.show() # Uncertainty data has pedigree in it. assert "pedigree" in wizard.obj.uncertainty # Go to the pedigree page with qtbot.waitSignal(wizard.currentIdChanged, timeout=100): wizard.type.pedigree.click() assert wizard.using_pedigree # Uncertainty/Pedigree data is valid loc, mean = float(wizard.pedigree.loc.text()), float( wizard.pedigree.mean.text()) assert np.isclose(np.exp(loc), mean) # The uncertainty should be positive assert not wizard.field("negative") wizard.pedigree.check_negative() assert not wizard.field("negative") # Alter mean and loc fields in turn to show balancing methods with qtbot.assertNotEmitted(wizard.pedigree.mean.textEdited): wizard.pedigree.mean.setText("") wizard.pedigree.balance_loc_with_mean() wizard.pedigree.check_negative() assert wizard.pedigree.loc.text() == "nan" # Setting the mean to a negative number will still return the same loc # value, but it will alter the 'negative' field. with qtbot.assertNotEmitted(wizard.pedigree.mean.textEdited): wizard.pedigree.mean.setText("-5") wizard.pedigree.balance_loc_with_mean() wizard.pedigree.check_negative() assert np.isclose(np.exp(float(wizard.pedigree.loc.text())), 5) assert wizard.field("negative")
def test_update_uncertainty(qtbot, ab_app): """Using the signal/controller setup, update the uncertainty of a parameter""" param = ProjectParameter.create(name="uc1", amount=3) wizard = UncertaintyWizard(param, None) qtbot.addWidget(wizard) wizard.show() wizard.type.distribution.setCurrentIndex(TriangularUncertainty.id) wizard.type.minimum.setText("1") wizard.type.maximum.setText("5") wizard.type.generate_plot() assert wizard.type.complete # Now trigger a 'finish' action with qtbot.waitSignal(signals.parameters_changed, timeout=100): wizard.button(QWizard.FinishButton).click() # Reload param param = ProjectParameter.get(name="uc1") assert "loc" in param.data and param.data["loc"] == 3
def test_uncertainty_wizard_simple(qtbot, bw2test, capsys): """Use extremely simple text to open the wizard and go to all the pages.""" param = ProjectParameter.create(name="test1", amount=3) wizard = UncertaintyWizard(param, None) qtbot.addWidget(wizard) wizard.show() assert "uncertainty type" in wizard.uncertainty_info wizard.extract_uncertainty() wizard.extract_lognormal_loc() # Go to the pedigree page with qtbot.waitSignal(wizard.currentIdChanged, timeout=100): wizard.type.pedigree.click() # Pedigree is empty, so complaint is issued. captured = capsys.readouterr() assert "Could not extract pedigree data" in captured.out # Now go back for giggles. with qtbot.waitSignal(wizard.currentIdChanged, timeout=100): wizard.button(QWizard.BackButton).click() assert not wizard.using_pedigree
def test_chain_loading_complicated(): Database("db").register() Group.create(name="D", order=[]) Group.create(name="E", order=[]) Group.create(name="B", order=["E"]) Group.create(name="C", order=["D", "E"]) Group.create(name="A", order=["C", "B"]) ProjectParameter.create( name="p1", amount=1, ) ProjectParameter.create( name="p2", amount=1, ) DatabaseParameter.create( database="db", name="db1", formula="2 * p1", amount=2, ) DatabaseParameter.create( database="db", name="db2", amount=2, ) ActivityParameter.create( group="D", database="db", code="D1", name="d1", formula="p1 + db1", amount=3, ) ActivityParameter.create( group="E", database="db", code="E1", name="e1", formula="p1 + p2 + db2", amount=4, ) ActivityParameter.create( group="C", database="db", code="C1", name="c1", formula="(e1 - d1) * 5", amount=5, ) ActivityParameter.create( group="B", database="db", code="B1", name="b1", formula="e1 * 2 - 2", amount=6, ) ActivityParameter.create( group="A", database="db", code="A1", name="a1", formula="b1 + c1 - db1 - 2", amount=7, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("A") pbm.load_parameter_data() expected = { 'A__a1': { 'amount': 7.0, 'code': 'A1', 'database': 'db', 'formula': '(((B__b1 + C__c1) - db__db1) - 2)', 'original': 'a1' }, 'B__b1': { 'amount': 6.0, 'code': 'B1', 'database': 'db', 'formula': '((E__e1 * 2) - 2)', 'original': 'b1' }, 'C__c1': { 'amount': 5.0, 'code': 'C1', 'database': 'db', 'formula': '((E__e1 - D__d1) * 5)', 'original': 'c1' }, 'D__d1': { 'amount': 3.0, 'code': 'D1', 'database': 'db', 'formula': '(project__p1 + db__db1)', 'original': 'd1' }, 'E__e1': { 'amount': 4.0, 'code': 'E1', 'database': 'db', 'formula': '((project__p1 + project__p2) + db__db2)', 'original': 'e1' }, 'db__db1': { 'amount': 2.0, 'database': 'db', 'formula': '(2 * project__p1)', 'original': 'db1' }, 'db__db2': { 'amount': 2.0, 'database': 'db', 'original': 'db2' }, 'project__p1': { 'amount': 1.0, 'original': 'p1' }, 'project__p2': { 'amount': 1.0, 'original': 'p2' } } assert pbm.data == expected
def test_load_existing_complete(): # Use same structure as in complicated example, but pre-create some presamples packages # Start with `project` ProjectParameter.create( name="p1", amount=1, ) ProjectParameter.create( name="p2", amount=1, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("project") pbm.load_parameter_data() result = pbm.calculate_static() expected = {'project__p1': 1, 'project__p2': 1} assert result == expected for obj in pbm.data.values(): obj['amount'] = 10 _, dirpath_project = pbm.save_presample('project-test') pp = PresamplesPackage(dirpath_project) assert len(pp) == 1 assert pp.parameters['project__p1'] == 10 # We will also do group 'D'; this will include database parameters, which will we purge ourselves Database("db").register() Group.create(name="D", order=[]) DatabaseParameter.create( database="db", name="db1", formula="2 * p1", amount=2, ) DatabaseParameter.create( database="db", name="db2", amount=2, ) ActivityParameter.create( group="D", database="db", code="D1", name="d1", formula="p1 + db1", amount=3, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("D") pbm.load_existing(dirpath_project) expected = {'project__p1': 10, 'project__p2': 10} assert pbm.global_params == expected pbm.load_parameter_data() expected = { 'D__d1': { 'database': 'db', 'code': 'D1', 'formula': '(project__p1 + db__db1)', 'amount': 3.0, 'original': 'd1' }, 'db__db1': { 'database': 'db', 'formula': '(2 * project__p1)', 'amount': 2.0, 'original': 'db1' }, 'db__db2': { 'database': 'db', 'amount': 2.0, 'original': 'db2' }, } assert pbm.data == expected # Want to calculate database parameters dynamically pbm.data = {'D__d1': pbm.data['D__d1']} pbm.data['D__d1']['amount'] = 12 _, dirpath_d = pbm.save_presample('D-test') pp = PresamplesPackage(dirpath_d) assert len(pp) == 1 assert pp.parameters['D__d1'] == 12 # Create rest of parameters Group.create(name="E", order=[]) Group.create(name="B", order=["E"]) Group.create(name="C", order=["D", "E"]) Group.create(name="A", order=["C", "B"]) ActivityParameter.create( group="E", database="db", code="E1", name="e1", formula="p1 + p2 + db2", amount=4, ) ActivityParameter.create( group="C", database="db", code="C1", name="c1", formula="(e1 - d1) * 5", amount=5, ) ActivityParameter.create( group="B", database="db", code="B1", name="b1", formula="e1 * 2 - 2", amount=6, ) ActivityParameter.create( group="A", database="db", code="A1", name="a1", formula="b1 + c1 - db1 - 2", amount=7, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("A") pbm.load_existing(dirpath_project) pbm.load_existing(dirpath_d) pbm.load_parameter_data() expected = { 'A__a1': { 'amount': 7.0, 'code': 'A1', 'database': 'db', 'formula': '(((B__b1 + C__c1) - db__db1) - 2)', 'original': 'a1' }, 'B__b1': { 'amount': 6.0, 'code': 'B1', 'database': 'db', 'formula': '((E__e1 * 2) - 2)', 'original': 'b1' }, 'C__c1': { 'amount': 5.0, 'code': 'C1', 'database': 'db', 'formula': '((E__e1 - D__d1) * 5)', 'original': 'c1' }, 'E__e1': { 'amount': 4.0, 'code': 'E1', 'database': 'db', 'formula': '((project__p1 + project__p2) + db__db2)', 'original': 'e1' }, 'db__db1': { 'amount': 2.0, 'database': 'db', 'formula': '(2 * project__p1)', 'original': 'db1' }, 'db__db2': { 'amount': 2.0, 'database': 'db', 'original': 'db2' }, } assert pbm.data == expected result = pbm.calculate_static() expected = { 'A__a1': 70.0, 'B__b1': 42.0, 'C__c1': 50.0, 'D__d1': 12.0, 'E__e1': 22.0, 'db__db1': 20.0, 'db__db2': 2.0, 'project__p1': 10, 'project__p2': 10, } assert result == expected pbm = ParameterizedBrightwayModel("A") pbm.load_existing(dirpath_project, only=['project__p1']) pbm.load_existing(dirpath_d) pbm.load_parameter_data() assert 'project__p2' in pbm.data assert 'project__p1' not in pbm.data
def test_chain_loading(): Database("B").register() Database("K").register() Group.create(name="G", order=["A"]) ActivityParameter.create( group="A", database="B", code="C", name="D", formula="2 ** 3", amount=1, ) ActivityParameter.create( group="A", database="B", code="E", name="F", formula="foo + bar + D", amount=2, ) ActivityParameter.create( group="G", database="K", code="H", name="J", formula="F + D * 2", amount=3, ) DatabaseParameter.create( database="B", name="foo", formula="2 ** 2", amount=5, ) ProjectParameter.create( name="bar", formula="2 * 2 * 2", amount=6, ) parameters.recalculate() m = ParameterizedBrightwayModel("A") m.load_parameter_data() expected = { 'A__D': { 'database': 'B', 'code': 'C', 'formula': '(2 ** 3)', 'amount': 8.0, 'original': 'D' }, 'A__F': { 'database': 'B', 'code': 'E', 'formula': '((B__foo + project__bar) + A__D)', 'amount': 20.0, 'original': 'F' }, 'B__foo': { 'database': 'B', 'formula': '(2 ** 2)', 'amount': 4.0, 'original': 'foo' }, 'project__bar': { 'formula': '((2 * 2) * 2)', 'amount': 8.0, 'original': 'bar' } } assert m.data == expected
def project_parameters(bw2test): ProjectParameter.create(name="test1", amount=3) ProjectParameter.create(name="test2", amount=5) ProjectParameter.create(name="test3", amount=7) return