def test_model_initialize(test_mp, caplog): # Model.initialize runs on an empty Scenario s = make_dantzig(test_mp) b1 = s.par('b') assert len(b1) == 3 # Modify a value for 'b' s.check_out() new_value = 301 s.add_par('b', 'chicago', new_value, 'cases') s.commit('Overwrite b(chicago)') # Model.initialize runs on an already-initialized Scenario, without error DantzigModel.initialize(s, with_data=True) # Data has the same length... b2 = s.par('b') assert len(b2) == 3 # ...but modified value(s) are not overwritten assert (b2.query("j == 'chicago'")['value'] == new_value).all() # Unrecognized Scenario(scheme=...) is initialized using the base method, a # no-op messages = [ "No scheme for new Scenario model-name/scenario-name", "No initialization for None-scheme Scenario", ] with assert_logs(caplog, messages, at_level=logging.DEBUG): Scenario(test_mp, model='model-name', scenario='scenario-name', version='new') with assert_logs(caplog, "No initialization for 'foo'-scheme Scenario", at_level=logging.DEBUG): Scenario(test_mp, model='model-name', scenario='scenario-name', version='new', scheme='foo') # Keyword arguments to Scenario(...) that are not recognized by # Model.initialize() raise an intelligible exception with pytest.raises(TypeError, match="unexpected keyword argument 'bad_arg1'"): Scenario(test_mp, model='model-name', scenario='scenario-name', version='new', scheme='unknown', bad_arg1=111) with pytest.raises(TypeError, match="unexpected keyword argument 'bad_arg2'"): Scenario(test_mp, model='model-name', scenario='scenario-name', version='new', scheme='dantzig', with_data=True, bad_arg2=222) # Replace b[j] with a parameter of the same name, but different indices s.check_out() s.remove_par('b') s.init_par('b', idx_sets=['i'], idx_names=['i_dim']) # Logs an error message with assert_logs(caplog, "Existing index sets of 'b' ['i'] do not match ['j']"): DantzigModel.initialize(s)
def test_model_initialize(test_mp, caplog): # Model.initialize runs on an empty Scenario s = make_dantzig(test_mp) b1 = s.par('b') assert len(b1) == 3 # Modify a value for 'b' s.check_out() s.add_par('b', 'chicago', 600, 'cases') s.commit('Overwrite b(chicago)') # Model.initialize runs on an already-initialized Scenario, without error DantzigModel.initialize(s, with_data=True) # Data has the same length... b2 = s.par('b') assert len(b2) == 3 # ...but modified value(s) are not overwritten assert (b2.query("j == 'chicago'")['value'] == 600).all() # Unrecognized Scenario(scheme=...) is initialized using the base method, a # no-op caplog.set_level(logging.DEBUG) Scenario(test_mp, model='model name', scenario='scenario name', version='new', scheme='unknown') assert caplog.records[-1].message == \ "No initialization for 'unknown'-scheme Scenario" # Keyword arguments to Scenario(...) that are not recognized by # Model.initialize() raise an intelligible exception with pytest.raises(TypeError, match="unexpected keyword argument 'bad_arg1'"): Scenario(test_mp, model='model name', scenario='scenario name', version='new', scheme='unknown', bad_arg1=111) with pytest.raises(TypeError, match="unexpected keyword argument 'bad_arg2'"): Scenario(test_mp, model='model name', scenario='scenario name', version='new', scheme='dantzig', with_data=True, bad_arg2=222)
def scen_with_big_data(self, test_mp, num_params=10): from itertools import zip_longest # test_mp.add_unit('kg') scen = Scenario(test_mp, 'TestQuantity', 'big data', version='new') # Dimensions and their lengths (Fibonacci numbers) N_dims = 6 dims = 'abcdefgh'[:N_dims + 1] sizes = [1, 5, 21, 21, 89, 377, 1597, 6765][:N_dims + 1] # commented: "377 / 73984365 elements = 0.00051% full" # from functools import reduce # from operator import mul # size = reduce(mul, sizes) # print('{} / {} elements = {:.5f}% full' # .format(max(sizes), size, 100 * max(sizes) / size)) # Names like f_0000 ... f_1596 along each dimension coords = [] for d, N in zip(dims, sizes): coords.append([f'{d}_{i:04d}' for i in range(N)]) # Add to Scenario scen.init_set(d) scen.add_set(d, coords[-1]) def _make_values(): """Make a DataFrame containing each label in *coords* ≥ 1 time.""" values = list(zip_longest(*coords, np.random.rand(max(sizes)))) result = pd.DataFrame(values, columns=list(dims) + ['value']) \ .ffill() result['unit'] = 'kg' return result # Fill the Scenario with quantities named q_01 ... q_09 names = [] for i in range(num_params): name = f'q_{i:02d}' scen.init_par(name, list(dims)) scen.add_par(name, _make_values()) names.append(name) yield scen
def test_maybe_commit(caplog, test_mp): s = Scenario(test_mp, "maybe_commit", "maybe_commit", version="new") # A new Scenario is not committed, so this works assert utils.maybe_commit(s, True, message="foo") is True # *s* is already commited. No commit is performed, but the function call # succeeds and a message is logged caplog.set_level(logging.INFO, logger="ixmp") assert utils.maybe_commit(s, True, message="foo") is False assert caplog.messages[-1].startswith("maybe_commit() didn't commit: ")
def test_store_ts(request, caplog, test_mp): # Computer and target scenario c = Computer() # Target scenario model_name = __name__ scenario_name = "test scenario" scen = Scenario(test_mp, model_name, scenario_name, version="new") scen.commit("Empty scenario") c.add("target", scen) # Add test data to the Computer: a pd.DataFrame input_1 = test_data[0].assign(variable="Foo") c.add("input 1", input_1) # A pyam.IamDataFrame input_2 = test_data[2050].assign(variable="Bar") c.add("input 2", pyam.IamDataFrame(input_2)) # Expected results: same as input, but with the `model` and `scenario` columns # filled automatically. expected_1 = input_1.assign(model=model_name, scenario=scenario_name) expected_2 = input_2.assign(model=model_name, scenario=scenario_name) # Task to update the scenario with the data c.add("test 1", store_ts, "target", "input 1", "input 2") # Scenario starts empty of time series data assert 0 == len(scen.timeseries()) # The computation runs successfully c.get("test 1") # All rows from both inputs are present assert len(input_1) + len(input_2) == len(scen.timeseries()) # Input is stored exactly assert_frame_equal(expected_1, scen.timeseries(variable="Foo")) assert_frame_equal(expected_2, scen.timeseries(variable="Bar"))
def test_error_message(self, test_data_path, test_mp): """GAMSModel.solve() displays a user-friendly message on error.""" # Empty Scenario s = Scenario(test_mp, model="foo", scenario="bar", version="new") s.commit("Initial commit") # Expected paths for error message paths = map( lambda name: re.escape(str(test_data_path.joinpath(name))), ["_abort.lst", "default_in.gdx"], ) with pytest.raises( ModelError, match="""GAMS errored with return code 2: There was a compilation error For details, see the terminal output above, plus: Listing : {} Input data: {}""".format(*paths), ): s.solve(model_file=test_data_path / "_abort.gms", use_temp_dir=False)
def test_timeseries_remove_all_data(mp): args_all = ('Douglas Adams', 'test_remove_all') scen = Scenario(mp, *args_all, version='new', annotation='fo') scen.add_timeseries(DATA['timeseries'].pivot_table(values='value', index=IDX_COLS)) scen.commit('importing a testing timeseries') scen = Scenario(mp, *args_all) assert_timeseries(scen, DATA['timeseries']) exp = DATA['timeseries'].copy() exp['variable'] = 'Testing2' scen.check_out() scen.add_timeseries(exp) scen.remove_timeseries(DATA['timeseries']) scen.commit('testing for removing a full timeseries row') assert scen.timeseries(region='World', variable='Testing').empty assert_timeseries(scen, exp)
def test_timeseries_remove_single_entry(mp): args_single = ('Douglas Adams', 'test_remove_single') scen = Scenario(mp, *args_single, version='new', annotation='fo') scen.add_timeseries(DATA['timeseries'].pivot_table(values='value', index=IDX_COLS)) scen.commit('importing a testing timeseries') scen = Scenario(mp, *args_single) assert_timeseries(scen, DATA['timeseries']) scen.check_out() scen.remove_timeseries(DATA['timeseries'][DATA['timeseries'].year == 2010]) scen.commit('testing for removing a single timeseries data point') exp = DATA['timeseries'][DATA['timeseries'].year == 2020] assert_timeseries(scen, exp)
def test_timeseries_remove_all_data(mp): args_all = ("Douglas Adams", "test_remove_all") scen = Scenario(mp, *args_all, version="new", annotation="fo") scen.add_timeseries(DATA["timeseries"].pivot_table(values="value", index=IDX_COLS)) scen.commit("importing a testing timeseries") scen = Scenario(mp, *args_all) assert_timeseries(scen, DATA["timeseries"]) exp = DATA["timeseries"].copy() exp["variable"] = "Testing2" scen.check_out() scen.add_timeseries(exp) scen.remove_timeseries(DATA["timeseries"]) scen.commit("testing for removing a full timeseries row") assert scen.timeseries(region="World", variable="Testing").empty assert_timeseries(scen, exp)
def test_timeseries_remove_single_entry(mp): args_single = ("Douglas Adams", "test_remove_single") scen = Scenario(mp, *args_single, version="new", annotation="fo") scen.add_timeseries(DATA["timeseries"].pivot_table(values="value", index=IDX_COLS)) scen.commit("importing a testing timeseries") scen = Scenario(mp, *args_single) assert_timeseries(scen, DATA["timeseries"]) scen.check_out() scen.remove_timeseries(DATA["timeseries"][DATA["timeseries"].year == 2010]) scen.commit("testing for removing a single timeseries data point") exp = DATA["timeseries"][DATA["timeseries"].year == 2020] assert_timeseries(scen, exp)
def add_par_setup(mp, length): # pragma: no cover return (Scenario(mp, **models["dantzig"], version="new"), length), dict()
def make_dantzig(mp: Platform, solve: bool = False, quiet: bool = False) -> Scenario: """Return :class:`ixmp.Scenario` of Dantzig's canning/transport problem. Parameters ---------- mp : .Platform Platform on which to create the scenario. solve : bool, optional If :obj:`True`. then solve the scenario before returning. Default :obj:`False`. quiet : bool, optional If :obj:`True`, suppress console output when solving. Returns ------- .Scenario See also -------- .DantzigModel """ # add custom units and region for timeseries data try: mp.add_unit("USD/km") except Exception: # Unit already exists. Pending bugfix from zikolach pass mp.add_region("DantzigLand", "country") # Initialize a new Scenario, and use the DantzigModel class' initialize() # method to populate it annot = "Dantzig's transportation problem for illustration and testing" scen = Scenario( mp, **models["dantzig"], # type: ignore [arg-type] version="new", annotation=annot, scheme="dantzig", with_data=True, ) # commit the scenario scen.commit("Import Dantzig's transport problem for testing.") # set this new scenario as the default version for the model/scenario name scen.set_as_default() if solve: # Solve the model using the GAMS code provided in the `tests` folder scen.solve(model="dantzig", case="transport_standard", quiet=quiet) # add timeseries data for testing `clone(keep_solution=False)` # and `remove_solution()` scen.check_out(timeseries_only=True) scen.add_timeseries(HIST_DF, meta=True) scen.add_timeseries(INP_DF) scen.commit("Import Dantzig's transport problem for testing.") return scen
def add_test_data(scen: Scenario): # New sets t_foo = ["foo{}".format(i) for i in (1, 2, 3)] t_bar = ["bar{}".format(i) for i in (4, 5, 6)] t = t_foo + t_bar y = list(map(str, range(2000, 2051, 10))) # Add to scenario scen.init_set("t") scen.add_set("t", t) scen.init_set("y") scen.add_set("y", y) # Data ureg = pint.get_application_registry() x = Quantity( xr.DataArray(np.random.rand(len(t), len(y)), coords=[("t", t), ("y", y)]), units=ureg.kg, ) # As a pd.DataFrame with units x_df = x.to_series().rename("value").reset_index() x_df["unit"] = "kg" scen.init_par("x", ["t", "y"]) scen.add_par("x", x_df) return t, t_foo, t_bar, x