def test_conflict_numpar_with_other_options(self): input_data = { "config": { "dispersion": { "hysplit": {'NUMPAR': 4000} } }, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 31.0, "lng": -64.0, "area": 10}]}]}]}, ] } with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( dict(dispersion_speed='faster'), handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.NUMPAR_CONFLICTS_WITH_OTHER_OPTIONS with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( dict(number_of_particles='medium'), handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.NUMPAR_CONFLICTS_WITH_OTHER_OPTIONS
def test_conflict_speed_with_other_options(self): input_data = { "config": { "dispersion": { "hysplit": {} } }, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 31.0, "lng": -64.0, "area": 10}]}]}]}, ] } with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( dict(dispersion_speed='balanced', number_of_particles='low'), handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.DISPERSION_SPEED_CONFLICTS_WITH_OTHER_OPTIONS with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( dict(dispersion_speed='balanced', grid_resolution='low'), handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.DISPERSION_SPEED_CONFLICTS_WITH_OTHER_OPTIONS
def test_invalid_options(self): input_data = { "config": { "dispersion": { "hysplit": {} } }, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 31.0, "lng": -64.0, "area": 10}]}]}]}, ] } with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( dict(dispersion_speed='sdfsdf'), handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.INVALID_DISPERSION_SPEED.format('sdfsdf') with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( dict(number_of_particles='sdfsdf'), handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.INVALID_NUMBER_OF_PARTICLES.format('sdfsdf') with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( dict(grid_resolution='sdfsdf'), handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.INVALID_GRID_RESOLUTION.format('sdfsdf')
def test_grid_with_other_options(self): input_data = { "config": { "dispersion": { "hysplit": { 'grid': { 'boundary': { 'ne': {'lat': 40.0, 'lng': -60.0}, 'sw': {'lat': 30.0, 'lng': -100.0} }, 'projection': 'LCC', 'spacing': 2.0 } } } }, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 31.0, "lng": -64.0, "area": 10}]}]}]}, ] } with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( dict(dispersion_speed='faster'), handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.GRID_CONFLICTS_WITH_OTHER_OPTIONS with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( dict(grid_resolution='medium'), handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.GRID_CONFLICTS_WITH_OTHER_OPTIONS
def test_with_grid(self): input_data = { "config": { "dispersion": { "hysplit": { # 'grid' "grid": { "spacing": 2, "projection": "LCC", "boundary": { "sw": {"lng": -100.0, "lat": 30.0}, "ne": {"lng": -60.0, "lat": 40.0} } } } } }, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 31.0, "lng": -64.0, "area": 10}]}]}]}, ] } hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) assert 'USER_DEFINED_GRID' not in hycon._hysplit_config assert 'compute_grid' not in hycon._hysplit_config expected_grid = { "spacing": 2, "projection": "LCC", "boundary": { "sw": {"lng": -100.0, "lat": 30.0}, "ne": {"lng": -60.0, "lat": 40.0} } } assert hycon._hysplit_config['grid'] == expected_grid
def test_reduced_fire_in_middle(self): """This tests the case where the grid is reduced, and the fire is central enough so that the reduced grid can be centered around it. """ input_data = { "config": {"dispersion": {}}, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 37.0, "lng": -84.0, "area": 10}], "ecoregion": "western","utc_offset": '-05:00'}]}]}, ] } hycon = hysplit.HysplitConfigurator( dict(grid_size=0.50), handle_error, input_data, ARCHIVE_INFO) hycon._configure_hysplit_reduced_grid() expected_grid = { 'boundary': { "sw": {"lng": -94.0, "lat": 34.5}, "ne": {"lng": -74.0, "lat": 39.5} }, 'projection': 'LCC', 'spacing': 2.0 } assert hycon._hysplit_config['grid'] == expected_grid
async def _configure_dispersion(self, data): tornado.log.gen_log.debug('Configuring dispersion') if (not data.get('config', {}).get('dispersion', {}) or not data['config']['dispersion'].get('start') or not data['config']['dispersion'].get('num_hours')): self.handle_error(400, "dispersion 'start' and 'num_hours' must be specified") return data['config']['dispersion']['handle_existing'] = "replace" data['config']['dispersion']['output_dir'] = os.path.join( self.settings['output_root_dir'], self.settings['output_url_path_prefix'], '{run_id}', 'output') data['config']['dispersion']['working_dir'] = os.path.join( self.settings['output_root_dir'], self.settings['output_url_path_prefix'], '{run_id}', 'working') tornado.log.gen_log.debug("Output dir: %s", data['config']['dispersion']['output_dir']) tornado.log.gen_log.debug("Working dir: %s", data['config']['dispersion']['working_dir']) if not self.archive_id: data['config']['dispersion']['model'] = 'vsmoke' if data['config']['dispersion'].get('model') in ('hysplit', None): configurator = hysplit.HysplitConfigurator( self.hysplit_query_params, self.handle_error, data, self.archive_info) data['config']['dispersion']['hysplit'] = configurator.config
def test_custom_numpar(self): input_data = { "config": { "dispersion": { "hysplit": {"NUMPAR": 4500} } }, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 31.0, "lng": -64.0, "area": 10}]}]}]}, ] } hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) expected_hysplit_config = { 'DELT': 0.0, 'INITD': 0, 'KHMAX': 72, 'MAXPAR': 1000000000, 'MPI': True, 'NCPUS': 4, 'NINIT': 0, 'NUMPAR': 4500, 'VERTICAL_EMISLEVELS_REDUCTION_FACTOR': 5, 'VERTICAL_LEVELS': [100], 'grid': { 'boundary': { 'ne': {'lat': 40.0, 'lng': -60.0}, 'sw': {'lat': 30.0, 'lng': -100.0} }, 'projection': 'LCC', 'spacing': 2.0 } } assert hycon._hysplit_config == expected_hysplit_config
def test_reduced_fire_in_upper_right(self): """This tests the case where the grid is reduced, and the fire is far enough in the corner of the archive's full grid that it's also toward the corner in the reduced grid. """ input_data = { "config": {"dispersion": {}}, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 31.0, "lng": -64.0, "area": 10}], "ecoregion": "western","utc_offset": '-05:00'}]}]}, ] } hycon = hysplit.HysplitConfigurator( dict(grid_size=0.50), handle_error, input_data, ARCHIVE_INFO) hycon._configure_hysplit_reduced_grid() expected_grid = { 'boundary': { "sw": {"lng": -80.0, "lat": 30.0}, "ne": {"lng": -60.0, "lat": 35.0} }, 'projection': 'LCC', 'spacing': 2.0 } assert hycon._hysplit_config['grid'] == expected_grid
def test_user_defined_grid_too_far_east(self): input_data = copy.deepcopy(self.USER_DEFINED_GRID_INPUT_DATA) input_data["config"]["dispersion"]["hysplit"]["CENTER_LONGITUDE"] = -75 with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.USER_DEFINED_GRID_OUTSIDE_MET_BOUNDS
def test_with_grid_too_far_east(self): input_data = copy.deepcopy(self.GRID_INPUT_DATA) input_data["config"]["dispersion"]["hysplit"]["grid"]["boundary"]["ne"]["lng"] = -55 with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.GRID_OUTSIDE_MET_BOUNDS
def setup(self): input_data = { "config": {"dispersion": {}}, "fires": [{ "activity": [{ "active_areas": [] }] }] } self.active_areas = input_data["fires"][0]["activity"][0]["active_areas"] self.hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO)
def test_missing_lat(self): input_data = { "config": {"dispersion": {}}, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lng": -89.0, "area": 10}], "ecoregion": "western","utc_offset": '-05:00'}]}]}, ] } hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) with pytest.raises(MockHTTPError) as e: hycon._configure_hysplit_reduced_grid() assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.INVALID_FIRE_LOCATION_INFO
def test_with_grid_equal_to_archive_boundary(self): input_data = copy.deepcopy(self.GRID_INPUT_DATA) hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) assert 'USER_DEFINED_GRID' not in hycon._hysplit_config assert 'compute_grid' not in hycon._hysplit_config expected_grid = { "spacing": 2, "projection": "LCC", "boundary": { "sw": {"lng": -100.0, "lat": 30.0}, "ne": {"lng": -60.0, "lat": 40.0} } } assert hycon._hysplit_config['grid'] == expected_grid
def test_user_defined_grid_equal_to_archive_boundary(self): input_data = copy.deepcopy(self.USER_DEFINED_GRID_INPUT_DATA) hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) assert 'grid' not in hycon._hysplit_config assert 'compute_grid' not in hycon._hysplit_config expected_params = { "USER_DEFINED_GRID": True, "CENTER_LATITUDE": 35, "CENTER_LONGITUDE": -80, "HEIGHT_LATITUDE": 10, "WIDTH_LONGITUDE": 40, "SPACING_LONGITUDE": 2, "SPACING_LATITUDE": 2, } for k in expected_params: assert hycon._hysplit_config[k] == expected_params[k]
def test_multiple_fire_objects(self): input_data = { "config": {"dispersion": {}}, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 37.0, "lng": -89.0, "area": 10}], "ecoregion": "western","utc_offset": '-05:00'}]}]}, {"activity": [{"active_areas": [{ "specified_points": [{"lat": 32.0, "lng": -112.0, "area": 15}], "ecoregion": "western","utc_offset": '-06:00'}]}]}, ] } hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) with pytest.raises(MockHTTPError) as e: hycon._configure_hysplit_reduced_grid() assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.SINGLE_FIRE_ONLY
def test_use_default_grid(self): input_data = { "config": { "dispersion": { "hysplit": { } } }, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 31.0, "lng": -64.0, "area": 10}]}]}]}, ] } hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) assert 'USER_DEFINED_GRID' not in hycon._hysplit_config assert 'compute_grid' not in hycon._hysplit_config assert hycon._hysplit_config['grid'] == ARCHIVE_INFO['grid']
def test_with_grid_within_archive_boundary(self): input_data = copy.deepcopy(self.GRID_INPUT_DATA) input_data["config"]["dispersion"]["hysplit"]["grid"]["boundary"]["sw"]["lat"] = 32 input_data["config"]["dispersion"]["hysplit"]["grid"]["boundary"]["sw"]["lng"] = -95 input_data["config"]["dispersion"]["hysplit"]["grid"]["boundary"]["ne"]["lat"] = 38 input_data["config"]["dispersion"]["hysplit"]["grid"]["boundary"]["ne"]["lng"] = -65 hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) assert 'USER_DEFINED_GRID' not in hycon._hysplit_config assert 'compute_grid' not in hycon._hysplit_config expected_grid = { "spacing": 2, "projection": "LCC", "boundary": { "sw": {"lng": -95.0, "lat": 32.0}, "ne": {"lng": -65.0, "lat": 38.0} } } assert hycon._hysplit_config['grid'] == expected_grid
def test_no_options_nam3km(self): input_data = { "config": { "dispersion": { "hysplit": {} } }, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 31.0, "lng": -64.0, "area": 10}]}]}]}, ] } archive_info = copy.deepcopy(ARCHIVE_INFO) archive_info['domain_id'] = 'NAM3km' hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, archive_info) expected_hysplit_config = { 'DELT': 0.0, 'INITD': 0, 'KHMAX': 72, 'MAXPAR': 1000000000, 'MPI': True, 'NCPUS': 4, 'NINIT': 0, 'NUMPAR': 2000, 'VERTICAL_EMISLEVELS_REDUCTION_FACTOR': 5, 'VERTICAL_LEVELS': [100], 'DISPERSION_OFFSET': 1, 'ensure_dummy_fire': False, 'grid': { 'boundary': { 'ne': {'lat': 40.0, 'lng': -60.0}, 'sw': {'lat': 30.0, 'lng': -100.0} }, 'projection': 'LCC', 'spacing': 2.0 } } assert hycon._hysplit_config == expected_hysplit_config
def test_faster_dispersion_speed(self): input_data = { "config": { "dispersion": { "hysplit": {} } }, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 34.0, "lng": -64.0, "area": 10}]}]}]}, ] } hycon = hysplit.HysplitConfigurator( dict(dispersion_speed='faster'), handle_error, input_data, ARCHIVE_INFO) expected_hysplit_config = { 'DELT': 0.0, 'INITD': 0, 'KHMAX': 72, 'MAXPAR': 1000000000, 'MPI': True, 'NCPUS': 4, 'NINIT': 0, 'NUMPAR': 1000, 'VERTICAL_EMISLEVELS_REDUCTION_FACTOR': 5, 'VERTICAL_LEVELS': [100], 'ensure_dummy_fire': False, 'grid': { 'boundary': { 'ne': {'lat': 35.25, 'lng': -60.0}, 'sw': {'lat': 32.75, 'lng': -70.0} }, 'projection': 'LCC', 'spacing': 3.0 } } assert hycon._hysplit_config == expected_hysplit_config
def test_polygon_reduced_fire_in_middle(self): """This tests the case where the grid is reduced, and the fire is central enough so that the reduced grid can be centered around it, and the fire has polygon geometry. """ input_data = { "config": {"dispersion": {}}, "fires": [{ "activity": [{ "active_areas": [{ "perimeter": { "area": 10, "polygon": [ [-85.0, 38.0], [-85.0, 36.0], [-83.0, 36.0], [-83.0, 38.0], [-85.0, 38.0] ] } }] }] }] } hycon = hysplit.HysplitConfigurator( dict(grid_size=0.50), handle_error, input_data, ARCHIVE_INFO) hycon._configure_hysplit_reduced_grid() expected_grid = { 'boundary': { "sw": {"lng": -94.0, "lat": 34.5}, "ne": {"lng": -74.0, "lat": 39.5} }, 'projection': 'LCC', 'spacing': 2.0 } assert hycon._hysplit_config['grid'] == expected_grid
def test_too_many_grid_definitions(self): input_data = { "config": { "dispersion": { "hysplit": { # 'grid' "grid": { "spacing": 2, "projection": "LCC", "boundary": { "sw": {"lng": -100.0, "lat": 30.0}, "ne": {"lng": -60.0, "lat": 40.0} } }, # 'USER_DEFINED_GRID' "USER_DEFINED_GRID": True, "CENTER_LATITUDE": 40, "CENTER_LONGITUDE": -80, "HEIGHT_LATITUDE": 20, "WIDTH_LONGITUDE": 40, "SPACING_LONGITUDE": 2, "SPACING_LATITUDE": 2, # 'compute_grid' "compute_grid": True }, } }, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 31.0, "lng": -64.0, "area": 10}]}]}]}, ] } with pytest.raises(MockHTTPError) as e: hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) assert e.value.status_code == 400 assert e.value.msg == hysplit.ErrorMessages.TOO_MANY_GRID_SPECIFICATIONS
def test_not_reduced(self): """This tests the case where the grid is not reduced - it is left as defined for the archive. """ input_data = { "config": {"dispersion": {}}, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 37.0, "lng": -89.0, "area": 10}], "ecoregion": "western","utc_offset": '-05:00'}]}]}, ] } hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) hycon._configure_hysplit_reduced_grid() expected_grid = { 'boundary': { "sw": {"lng": -100.0, "lat": 30.0}, "ne": {"lng": -60.0, "lat": 40.0} }, 'projection': 'LCC', 'spacing': 2.0 } assert hycon._hysplit_config['grid'] == expected_grid
def test_user_defined_grid(self): input_data = { "config": { "dispersion": { "hysplit": { # 'USER_DEFINED_GRID' "USER_DEFINED_GRID": True, "CENTER_LATITUDE": 40, "CENTER_LONGITUDE": -80, "HEIGHT_LATITUDE": 20, "WIDTH_LONGITUDE": 40, "SPACING_LONGITUDE": 2, "SPACING_LATITUDE": 2, } } }, "fires": [ {"activity": [{"active_areas": [{ "specified_points": [{"lat": 31.0, "lng": -64.0, "area": 10}]}]}]}, ] } hycon = hysplit.HysplitConfigurator( {}, handle_error, input_data, ARCHIVE_INFO) assert 'grid' not in hycon._hysplit_config assert 'compute_grid' not in hycon._hysplit_config expected_params = { "USER_DEFINED_GRID": True, "CENTER_LATITUDE": 40, "CENTER_LONGITUDE": -80, "HEIGHT_LATITUDE": 20, "WIDTH_LONGITUDE": 40, "SPACING_LONGITUDE": 2, "SPACING_LATITUDE": 2, } for k in expected_params: assert hycon._hysplit_config[k] == expected_params[k]