def test_data_list_to_array(self): data = [{ 'year': 2010, 'value': 3, 'region': 'oxford', 'interval': 1 }, { 'year': 2011, 'value': 5, 'region': 'oxford', 'interval': 1 }, { 'year': 2012, 'value': 1, 'region': 'oxford', 'interval': 1 }] builder = SosModelBuilder() spatial = builder.region_register.get_entry('LSOA') temporal = builder.interval_register.get_entry('annual') actual = builder._data_list_to_array('raininess', data, [2010, 2011, 2012], spatial, temporal) expected = np.array([[[3.]], [[5.]], [[1.]]], dtype=float) np.testing.assert_equal(actual, expected)
def test_scenario_data_missing_param_interval( self, setup_region_data, ): data = { "length": [{ 'value': 3.14, 'region': 'oxford', 'interval': 1, 'year': 2015 }, { 'value': 3.14, 'region': 'oxford', 'interval': 'extra', 'year': 2015 }] } builder = SosModelBuilder() msg = "Interval 'extra' not defined in set 'annual' for parameter 'length'" with raises(ValueError) as ex: builder.load_scenario_models([{ 'name': 'length', 'spatial_resolution': 'LSOA', 'temporal_resolution': 'annual', 'units': 'm' }], data, [2015]) assert msg in str(ex)
def test_cyclic_dependencies(self, get_sos_model_config_with_summed_dependency): config_data = get_sos_model_config_with_summed_dependency builder = SosModelBuilder() with raises(NotImplementedError): builder.construct(config_data)
def test_set_max_iterations(self, get_sos_model_config): """Test constructing from single dict config """ config = get_sos_model_config config['max_iterations'] = 125 builder = SosModelBuilder() builder.construct(config) sos_model = builder.finish() assert sos_model.max_iterations == 125
def test_set_convergence_relative_tolerance(self, get_sos_model_config): """Test constructing from single dict config """ config = get_sos_model_config config['convergence_relative_tolerance'] = 0.1 builder = SosModelBuilder() builder.construct(config) sos_model = builder.finish() assert sos_model.convergence_relative_tolerance == 0.1
def test_set_convergence_absolute_tolerance(self, get_sos_model_config): """Test constructing from single dict config """ config = get_sos_model_config config['convergence_absolute_tolerance'] = 0.0001 builder = SosModelBuilder() builder.construct(config, [2010, 2011, 2012]) sos_model = builder.finish() assert sos_model.convergence_absolute_tolerance == 0.0001
def test_load_scenario_models(self, get_sos_model_config): config = get_sos_model_config builder = SosModelBuilder() builder.construct(config, [2010]) sos_model = builder.finish() scenario = sos_model.models['raininess'] expected = {'raininess': {'raininess': np.array([[3.]])}} assert scenario.simulate(2010) == expected
def test_construct(self, get_sos_model_config): """Test constructing from single dict config """ config = get_sos_model_config builder = SosModelBuilder() builder.construct(config) sos_model = builder.finish() assert isinstance(sos_model, SosModel) assert list(sos_model.sector_models.keys()) == ['water_supply'] assert isinstance(sos_model.models['water_supply'], SectorModel)
def test_builder_interventions(self, get_sos_model_config): builder = SosModelBuilder() config_data = get_sos_model_config builder.construct(config_data, config_data['timesteps']) sos_model = builder.finish() assert sos_model.sector_models == ['water_supply'] assert sos_model.intervention_names == [ "water_asset_a", "water_asset_b", "water_asset_c" ]
def test_scenario_data_missing_param_mapping(self): data = {"length": [{'value': 3.14, 'year': 2015}]} builder = SosModelBuilder() msg = "Parameter 'bla_length' in scenario definitions not registered in scenario data" with raises(ValueError) as ex: builder.load_scenario_models([{ 'name': 'bla_length', 'spatial_resolution': 'LSOA', 'temporal_resolution': 'annual', 'units': 'm' }], data, [2015]) assert msg in str(ex.value)
def get_sos_model_with_summed_dependency(setup_region_data): builder = SosModelBuilder() builder.load_scenario_models( [{ 'name': 'raininess', 'temporal_resolution': 'annual', 'spatial_resolution': 'LSOA', 'units': 'ml' }], { "raininess": [{ 'year': 2010, 'value': 3, 'region': 'oxford', 'interval': 1 }] }, [2010, 2011, 2012]) sos_model = builder.finish() region_register = sos_model.regions interval_register = sos_model.intervals raininess_model = sos_model.models['raininess'] ws = WaterSupplySectorModel('water_supply') ws.add_input('raininess', region_register.get_entry('LSOA'), interval_register.get_entry('annual'), 'ml') ws.add_output('water', region_register.get_entry('LSOA'), interval_register.get_entry('annual'), 'Ml') ws.add_dependency(raininess_model, 'raininess', 'raininess') sos_model.add_model(ws) ws2 = WaterSupplySectorModel('water_supply_2') ws2.add_input('raininess', region_register.get_entry('LSOA'), interval_register.get_entry('annual'), 'ml') ws2.add_output('water', region_register.get_entry('LSOA'), interval_register.get_entry('annual'), 'Ml') ws2.add_dependency(raininess_model, 'raininess', 'raininess') sos_model.add_model(ws2) ws3 = WaterSupplySectorModel('water_supply_3') ws3.add_input('water', region_register.get_entry('LSOA'), interval_register.get_entry('annual'), 'Ml') # TODO implement summed dependency # ws3.add_dependency(ws, 'water', 'water') ws3.add_dependency(ws2, 'water', 'water') sos_model.add_model(ws3) return sos_model
def test_scenarios(self, get_sos_model_config): """Test constructing from single dict config """ config = get_sos_model_config builder = SosModelBuilder() builder.construct(config, [2010, 2011, 2012]) sos_model = builder.finish() assert isinstance(sos_model, SosModel) assert sos_model.sector_models == ['water_supply'] assert isinstance(sos_model.models['water_supply'], SectorModel) assert isinstance(sos_model.models['raininess'], ScenarioModel) actual = sos_model.models['raininess']._data np.testing.assert_equal( actual, np.array([[[3.]], [[5.]], [[1.]]], dtype=float))
def test_scenario_data_missing_year( self, setup_region_data, ): data = {"length": [{'value': 3.14}]} builder = SosModelBuilder() msg = "Scenario data item missing year" with raises(ValueError) as ex: builder.load_scenario_models([{ 'name': 'length', 'spatial_resolution': 'LSOA', 'temporal_resolution': 'annual', 'units': 'm' }], data, [2015]) assert msg in str(ex.value)
def test_scenario_data_defaults(self, setup_region_data): data = { "length": [{ 'year': 2015, 'interval': 1, 'value': 3.14, 'region': 'oxford' }] } expected = np.array([[[3.14]]]) builder = SosModelBuilder() builder.load_scenario_models([{ 'name': 'length', 'spatial_resolution': 'LSOA', 'temporal_resolution': 'annual', 'units': 'm' }], data, [2015]) assert builder.sos_model.models['length']._data == expected
def test_simple_dependency(self, get_sos_model_config_with_dep): config_data = get_sos_model_config_with_dep builder = SosModelBuilder() builder.construct(config_data, config_data['timesteps']) sos_model = builder.finish() sos_model.check_dependencies() graph = sos_model.dependency_graph scenario = sos_model.models['raininess'] assert 'water_supply' in sos_model.models assert sos_model.models['water_supply'] in graph.nodes() deps = sos_model.models['water_supply'].deps assert 'raininess' in deps.keys() expected = Dependency(scenario, scenario.model_outputs['raininess']) assert deps['raininess'] == expected assert 'raininess' in sos_model.models assert sos_model.models['raininess'] in graph.nodes()
def get_sos_model_with_summed_dependency(oxford_region): scenario_model = get_scenario_model_object builder = SosModelBuilder() builder.load_scenario_models([scenario_model]) sos_model = builder.finish() region_register = sos_model.regions interval_register = sos_model.intervals raininess_model = sos_model.models['raininess'] ws = WaterSupplySectorModel('water_supply') ws.add_input('raininess', region_register.get_entry('LSOA'), interval_register.get_entry('annual'), 'ml') ws.add_output('water', region_register.get_entry('LSOA'), interval_register.get_entry('annual'), 'Ml') ws.add_dependency(raininess_model, 'raininess', 'raininess') sos_model.add_model(ws) ws2 = WaterSupplySectorModel('water_supply_2') ws2.add_input('raininess', region_register.get_entry('LSOA'), interval_register.get_entry('annual'), 'ml') ws2.add_output('water', region_register.get_entry('LSOA'), interval_register.get_entry('annual'), 'Ml') ws2.add_dependency(raininess_model, 'raininess', 'raininess') sos_model.add_model(ws2) ws3 = WaterSupplySectorModel('water_supply_3') ws3.add_input('water', region_register.get_entry('LSOA'), interval_register.get_entry('annual'), 'Ml') # TODO implement summed dependency # ws3.add_dependency(ws, 'water', 'water') ws3.add_dependency(ws2, 'water', 'water') sos_model.add_model(ws3) return sos_model
def test_missing_planning_asset(self, get_sos_model_config): config = get_sos_model_config config["planning"] = [{ "name": "test_intervention", "build_date": 2012 }] builder = SosModelBuilder() builder.construct(config, [2010, 2011, 2012]) with raises(AssertionError) as ex: builder.finish() assert "Intervention 'test_intervention' in planning file not found" in str( ex.value)
def test_scenario_dependency(self, get_sos_model_config, setup_region_data): """Expect successful build with dependency on scenario data Should raise error if no spatial or temporal sets are defined """ config = get_sos_model_config config["sector_model_data"][0]["inputs"] = [{ 'name': 'raininess', 'spatial_resolution': 'blobby', 'temporal_resolution': 'annual', 'units': 'ml' }] builder = SosModelBuilder() with raises(ValueError): builder.construct(config, [2010, 2011, 2012]) builder.region_register.register( RegionSet('blobby', setup_region_data['features'])) interval_data = [{'id': 'ultra', 'start': 'P0Y', 'end': 'P1Y'}] builder.interval_register.register(IntervalSet('mega', interval_data)) builder.construct(config, [2010, 2011, 2012])
def test_nest_scenario_data(self, setup_country_data): data = { "mass": [{ 'year': 2015, 'region': 'GB', 'interval': 'wet_season', 'value': 3 }, { 'year': 2015, 'region': 'GB', 'interval': 'dry_season', 'value': 5 }, { 'year': 2015, 'region': 'NI', 'interval': 'wet_season', 'value': 1 }, { 'year': 2015, 'region': 'NI', 'interval': 'dry_season', 'value': 2 }, { 'year': 2016, 'region': 'GB', 'interval': 'wet_season', 'value': 4 }, { 'year': 2016, 'region': 'GB', 'interval': 'dry_season', 'value': 6 }, { 'year': 2016, 'region': 'NI', 'interval': 'wet_season', 'value': 1 }, { 'year': 2016, 'region': 'NI', 'interval': 'dry_season', 'value': 2.5 }] } expected = np.array( [ # 2015 [ # GB [3, 5], # NI [1, 2] ], # 2016 [ # GB [4, 6], # NI [1, 2.5] ] ], dtype=float) builder = SosModelBuilder() interval_data = [ { 'id': 'wet_season', 'start': 'P0M', 'end': 'P5M' }, { 'id': 'dry_season', 'start': 'P5M', 'end': 'P10M' }, { 'id': 'wet_season', 'start': 'P10M', 'end': 'P1Y' }, ] builder.interval_register.register( IntervalSet('seasonal', interval_data)) builder.region_register.register( RegionSet('country', setup_country_data['features'])) builder.load_scenario_models([{ 'name': 'mass', 'spatial_resolution': 'country', 'temporal_resolution': 'seasonal', 'units': 'kg' }], data, [2015, 2016]) actual = builder.sos_model.models['mass']._data print(actual) print(expected) assert np.allclose(actual, expected)
def get_model_run_definition(args): """Builds the model run Returns ------- dict The complete sos_model_run configuration dictionary with contained ScenarioModel, SosModel and SectorModel objects """ handler = DatafileInterface(args.directory) load_region_sets(handler) load_interval_sets(handler) load_units(handler) try: model_run_config = handler.read_sos_model_run(args.modelrun) except DataNotFoundError: LOGGER.error("Model run %s not found. Run 'smif list' to see available model runs.", args.modelrun) exit(-1) LOGGER.info("Running %s", model_run_config['name']) LOGGER.debug("Model Run: %s", model_run_config) sos_model_config = handler.read_sos_model(model_run_config['sos_model']) sector_model_objects = [] for sector_model in sos_model_config['sector_models']: sector_model_config = handler.read_sector_model(sector_model) absolute_path = os.path.join(args.directory, sector_model_config['path']) sector_model_config['path'] = absolute_path intervention_files = sector_model_config['interventions'] intervention_list = [] for intervention_file in intervention_files: interventions = handler.read_interventions(intervention_file) intervention_list.extend(interventions) sector_model_config['interventions'] = intervention_list initial_condition_files = sector_model_config['initial_conditions'] initial_condition_list = [] for initial_condition_file in initial_condition_files: initial_conditions = handler.read_initial_conditions(initial_condition_file) initial_condition_list.extend(initial_conditions) sector_model_config['initial_conditions'] = initial_condition_list sector_model_builder = SectorModelBuilder(sector_model_config['name']) LOGGER.debug("Sector model config: %s", sector_model_config) sector_model_builder.construct(sector_model_config, model_run_config['timesteps']) sector_model_object = sector_model_builder.finish() sector_model_objects.append(sector_model_object) LOGGER.debug("Model inputs: %s", sector_model_object.inputs.names) LOGGER.debug("Sector models: %s", sector_model_objects) sos_model_config['sector_models'] = sector_model_objects scenario_objects = [] for scenario_set, scenario_name in model_run_config['scenarios'].items(): scenario_definition = handler.read_scenario_definition(scenario_name) LOGGER.debug("Scenario definition: %s", scenario_definition) scenario_model_builder = ScenarioModelBuilder(scenario_set) scenario_model_builder.construct(scenario_definition) scenario_objects.append(scenario_model_builder.finish()) LOGGER.debug("Scenario models: %s", [model.name for model in scenario_objects]) sos_model_config['scenario_sets'] = scenario_objects sos_model_builder = SosModelBuilder() sos_model_builder.construct(sos_model_config) sos_model_object = sos_model_builder.finish() LOGGER.debug("Model list: %s", list(sos_model_object.models.keys())) model_run_config['sos_model'] = sos_model_object narrative_objects = get_narratives(handler, model_run_config['narratives']) model_run_config['narratives'] = narrative_objects return model_run_config
def _add_sos_model(self, config_data): """ """ builder = SosModelBuilder() builder.construct(config_data, self.model_run.model_horizon) self.model_run.sos_model = builder.finish()