def test_biophysical_table_missing_lucode(self): """SWY test bad biophysical table with missing LULC value.""" from natcap.invest.seasonal_water_yield import seasonal_water_yield import pygeoprocessing # use predefined directory so test can clean up files during teardown args = SeasonalWaterYieldRegressionTests.generate_base_args( self.workspace_dir) # make args explicit that this is a base run of SWY args['user_defined_climate_zones'] = False args['user_defined_local_recharge'] = False args['monthly_alpha'] = False args['results_suffix'] = '' # add a LULC value not found in biophysical csv lulc_new_path = os.path.join(self.workspace_dir, 'lulc_new.tif') lulc_info = pygeoprocessing.get_raster_info(args['lulc_raster_path']) lulc_array = gdal.OpenEx(args['lulc_raster_path']).ReadAsArray() lulc_array[0][0] = 321 # set a nodata value to make sure nodatas are handled correctly when # reclassifying lulc_array[0][1] = lulc_info['nodata'][0] pygeoprocessing.numpy_array_to_raster( lulc_array, lulc_info['nodata'][0], lulc_info['pixel_size'], (lulc_info['geotransform'][0], lulc_info['geotransform'][3]), lulc_info['projection_wkt'], lulc_new_path) lulc_array = None args['lulc_raster_path'] = lulc_new_path with self.assertRaises(ValueError) as context: seasonal_water_yield.execute(args) self.assertTrue( ("The missing values found in the LULC raster but not the" " table are: [321]") in str(context.exception))
def test_user_recharge(self): """SWY user recharge regression test on sample data Executes SWY in user defined local recharge mode and checks that the output files are generated and that the aggregate shapefile fields are the same as the regression case.""" from natcap.invest.seasonal_water_yield import seasonal_water_yield # use predefined directory so test can clean up files during teardown args = SeasonalWaterYieldRegressionTests.generate_base_args( self.workspace_dir) # modify args to account for user recharge args['user_defined_climate_zones'] = False args['monthly_alpha'] = False args['results_suffix'] = '' args['user_defined_local_recharge'] = True recharge_ras_path = os.path.join(args['workspace_dir'], 'L.tif') make_recharge_raster(recharge_ras_path) args['l_path'] = recharge_ras_path seasonal_water_yield.execute(args) # generate aggregated results csv table for assertion agg_results_csv_path = os.path.join(args['workspace_dir'], 'agg_results_l.csv') make_agg_results_csv(agg_results_csv_path, recharge=True) SeasonalWaterYieldRegressionTests._assert_regression_results_equal( os.path.join(args['workspace_dir'], 'aggregated_results_swy.shp'), agg_results_csv_path)
def test_monthly_alpha_regression(self): """SWY monthly alpha values regression test on sample data Executes SWY using the monthly alpha table and checks that the output files are generated and that the aggregate shapefile fields are the same as the regression case.""" from natcap.invest.seasonal_water_yield import seasonal_water_yield # use predefined directory so test can clean up files during teardown args = SeasonalWaterYieldRegressionTests.generate_base_args( self.workspace_dir) # make args explicit that this is a base run of SWY args['user_defined_climate_zones'] = False args['user_defined_local_recharge'] = False args['monthly_alpha'] = True args['results_suffix'] = '' alpha_csv_path = os.path.join(args['workspace_dir'], 'monthly_alpha.csv') make_alpha_csv(alpha_csv_path) args['monthly_alpha_path'] = alpha_csv_path seasonal_water_yield.execute(args) # generate aggregated results csv table for assertion agg_results_csv_path = os.path.join(args['workspace_dir'], 'agg_results_base.csv') make_agg_results_csv(agg_results_csv_path) SeasonalWaterYieldRegressionTests._assert_regression_results_equal( os.path.join(args['workspace_dir'], 'aggregated_results_swy.shp'), agg_results_csv_path)
def test_precip_data_missing(self): """SWY test case where there is a missing precipitation file.""" from natcap.invest.seasonal_water_yield import seasonal_water_yield precip_dir_path = os.path.join(self.workspace_dir, 'precip_dir') test_precip_dir_path = os.path.join(self.workspace_dir, 'test_precip_dir') os.makedirs(precip_dir_path) make_precip_rasters(precip_dir_path) shutil.copytree(precip_dir_path, test_precip_dir_path) os.remove(os.path.join(test_precip_dir_path, 'precip_mm_3.tif')) # A placeholder args that has the property that the aoi_path will be # the same name as the output aggregate vector args = { 'workspace_dir': self.workspace_dir, 'alpha_m': '1/12', 'beta_i': '1.0', 'gamma': '1.0', 'precip_dir': test_precip_dir_path, # test constructed one 'threshold_flow_accumulation': '1000', 'user_defined_climate_zones': False, 'user_defined_local_recharge': False, 'monthly_alpha': False, } watershed_shp_path = os.path.join(args['workspace_dir'], 'watershed.shp') make_simple_shp(watershed_shp_path, (1180000.0, 690000.0)) args['aoi_path'] = watershed_shp_path biophysical_csv_path = os.path.join(args['workspace_dir'], 'biophysical_table.csv') make_biophysical_csv(biophysical_csv_path) args['biophysical_table_path'] = biophysical_csv_path dem_ras_path = os.path.join(args['workspace_dir'], 'dem.tif') make_gradient_raster(dem_ras_path) args['dem_raster_path'] = dem_ras_path eto_dir_path = os.path.join(args['workspace_dir'], 'eto_dir') os.makedirs(eto_dir_path) make_eto_rasters(eto_dir_path) args['et0_dir'] = eto_dir_path lulc_ras_path = os.path.join(args['workspace_dir'], 'lulc.tif') make_lulc_raster(lulc_ras_path) args['lulc_raster_path'] = lulc_ras_path rain_csv_path = os.path.join(args['workspace_dir'], 'rain_events_table.csv') make_rain_csv(rain_csv_path) args['rain_events_table_path'] = rain_csv_path soil_ras_path = os.path.join(args['workspace_dir'], 'soil_group.tif') make_soil_raster(soil_ras_path) args['soil_group_path'] = soil_ras_path with self.assertRaises(ValueError): seasonal_water_yield.execute(args)
def test_precip_data_missing(self): """SWY test case where there is a missing precipitation file""" from natcap.invest.seasonal_water_yield import seasonal_water_yield test_precip_dir = os.path.join(self.workspace_dir, 'test_precip_dir') shutil.copytree( os.path.join(SAMPLE_DATA, 'precip_dir'), test_precip_dir) os.remove(os.path.join(test_precip_dir, 'precip_mm_3.tif')) # A placeholder args that has the property that the aoi_path will be # the same name as the output aggregate vector args = { 'workspace_dir': self.workspace_dir, 'aoi_path': os.path.join(SAMPLE_DATA, 'watersheds.shp'), 'alpha_m': '1/12', 'beta_i': '1.0', 'biophysical_table_path': os.path.join( SAMPLE_DATA, 'biophysical_table.csv'), 'dem_raster_path': os.path.join(SAMPLE_DATA, 'dem.tif'), 'et0_dir': os.path.join(SAMPLE_DATA, 'eto_dir'), 'gamma': '1.0', 'lulc_raster_path': os.path.join(SAMPLE_DATA, 'lulc.tif'), 'precip_dir': test_precip_dir, # test constructed one 'rain_events_table_path': os.path.join( SAMPLE_DATA, 'rain_events_table.csv'), 'soil_group_path': os.path.join(SAMPLE_DATA, 'soil_group.tif'), 'threshold_flow_accumulation': '1000', 'user_defined_climate_zones': False, 'user_defined_local_recharge': False, 'monthly_alpha': False, } with self.assertRaises(ValueError): seasonal_water_yield.execute(args)
def test_climate_zones_regression(self): """SWY climate zone regression test on sample data Executes SWY in climate zones mode and checks that the output files are generated and that the aggregate shapefile fields are the same as the regression case.""" from natcap.invest.seasonal_water_yield import seasonal_water_yield # use predefined directory so test can clean up files during teardown args = SeasonalWaterYieldRegressionTests.generate_base_args( self.workspace_dir) # modify args to account for climate zones defined args['climate_zone_raster_path'] = os.path.join( SAMPLE_DATA, 'climate_zones.tif') args['climate_zone_table_path'] = os.path.join( SAMPLE_DATA, 'climate_zone_events.csv') args['user_defined_climate_zones'] = True args['user_defined_local_recharge'] = False args['monthly_alpha'] = False args['results_suffix'] = 'cz' seasonal_water_yield.execute(args) SeasonalWaterYieldRegressionTests._assert_regression_results_equal( args['workspace_dir'], os.path.join(REGRESSION_DATA, 'file_list_cz.txt'), os.path.join( args['workspace_dir'], 'aggregated_results_cz.shp'), os.path.join(REGRESSION_DATA, 'agg_results_cz.csv'))
def test_duplicate_aoi_assertion(self): """SWY ensure model halts when AOI path identical to output vector""" from natcap.invest.seasonal_water_yield import seasonal_water_yield # A placeholder args that has the property that the aoi_path will be # the same name as the output aggregate vector args = { 'workspace_dir': self.workspace_dir, 'aoi_path': os.path.join( self.workspace_dir, 'aggregated_results_foo.shp'), 'results_suffix': 'foo', 'alpha_m': '1/12', 'beta_i': '1.0', 'biophysical_table_path': os.path.join( SAMPLE_DATA, 'biophysical_table.csv'), 'dem_raster_path': os.path.join(SAMPLE_DATA, 'dem.tif'), 'et0_dir': os.path.join(SAMPLE_DATA, 'eto_dir'), 'gamma': '1.0', 'lulc_raster_path': os.path.join(SAMPLE_DATA, 'lulc.tif'), 'precip_dir': os.path.join(SAMPLE_DATA, 'precip_dir'), 'rain_events_table_path': os.path.join( SAMPLE_DATA, 'rain_events_table.csv'), 'soil_group_path': os.path.join(SAMPLE_DATA, 'soil_group.tif'), 'threshold_flow_accumulation': '1000', 'user_defined_climate_zones': False, 'user_defined_local_recharge': False, 'monthly_alpha': False, } with self.assertRaises(ValueError): seasonal_water_yield.execute(args)
def test_base_regression(self): """SWY base regression test on sample data Executes SWY in default mode and checks that the output files are generated and that the aggregate shapefile fields are the same as the regression case.""" from natcap.invest.seasonal_water_yield import seasonal_water_yield # use predefined directory so test can clean up files during teardown args = SeasonalWaterYieldRegressionTests.generate_base_args( self.workspace_dir) # Ensure the model can pass when a nodata value is not defined. srs = osr.SpatialReference() srs.ImportFromEPSG(26910) # UTM Zone 10N project_wkt = srs.ExportToWkt() size = 100 lulc_array = numpy.zeros((size, size), dtype=numpy.int8) lulc_array[size // 2:, :] = 1 driver = gdal.GetDriverByName('GTiff') new_raster = driver.Create(args['lulc_raster_path'], lulc_array.shape[0], lulc_array.shape[1], 1, gdal.GDT_Byte) band = new_raster.GetRasterBand(1) band.WriteArray(lulc_array) geotransform = [1180000, 1, 0, 690000, 0, -1] new_raster.SetGeoTransform(geotransform) band = None new_raster = None driver = None # make args explicit that this is a base run of SWY args['user_defined_climate_zones'] = False args['user_defined_local_recharge'] = False args['monthly_alpha'] = False args['results_suffix'] = '' seasonal_water_yield.execute(args) # generate aggregated results csv table for assertion agg_results_csv_path = os.path.join(args['workspace_dir'], 'agg_results_base.csv') make_agg_results_csv(agg_results_csv_path) SeasonalWaterYieldRegressionTests._assert_regression_results_equal( os.path.join(args['workspace_dir'], 'aggregated_results_swy.shp'), agg_results_csv_path)
def test_bad_biophysical_table(self): """SWY bad biophysical table with non-numerical values.""" from natcap.invest.seasonal_water_yield import seasonal_water_yield # use predefined directory so test can clean up files during teardown args = SeasonalWaterYieldRegressionTests.generate_base_args( self.workspace_dir) # make args explicit that this is a base run of SWY args['user_defined_climate_zones'] = False args['user_defined_local_recharge'] = False args['monthly_alpha'] = False args['results_suffix'] = '' make_bad_biophysical_csv(args['biophysical_table_path']) with self.assertRaises(ValueError) as context: seasonal_water_yield.execute(args) self.assertTrue( 'expecting all floating point numbers' in str(context.exception))
def test_climate_zones_missing_cz_id(self): """SWY climate zone regression test fails on bad cz table data. Executes SWY in climate zones mode and checks that the test fails when a climate zone raster value is not present in the climate zone table. """ from natcap.invest.seasonal_water_yield import seasonal_water_yield import pandas # use predefined directory so test can clean up files during teardown args = SeasonalWaterYieldRegressionTests.generate_base_args( self.workspace_dir) # modify args to account for climate zones defined cz_csv_path = os.path.join(args['workspace_dir'], 'climate_zone_events.csv') make_climate_zone_csv(cz_csv_path) args['climate_zone_table_path'] = cz_csv_path cz_ras_path = os.path.join(args['workspace_dir'], 'dem.tif') make_gradient_raster(cz_ras_path) args['climate_zone_raster_path'] = cz_ras_path # remove row from the climate zone table so cz raster value is missing bad_cz_table_path = os.path.join(self.workspace_dir, 'bad_climate_zone_table.csv') cz_df = pandas.read_csv(args['climate_zone_table_path']) cz_df = cz_df[cz_df['cz_id'] != 1] cz_df.to_csv(bad_cz_table_path) cz_df = None args['climate_zone_table_path'] = bad_cz_table_path args['user_defined_climate_zones'] = True args['user_defined_local_recharge'] = False args['monthly_alpha'] = False args['results_suffix'] = 'cz' with self.assertRaises(ValueError) as context: seasonal_water_yield.execute(args) self.assertTrue( ("The missing values found in the Climate Zone raster but not the" " table are: [1]") in str(context.exception))
def test_climate_zones_regression(self): """SWY climate zone regression test on sample data Executes SWY in climate zones mode and checks that the output files are generated and that the aggregate shapefile fields are the same as the regression case.""" from natcap.invest.seasonal_water_yield import seasonal_water_yield # use predefined directory so test can clean up files during teardown args = SeasonalWaterYieldRegressionTests.generate_base_args( self.workspace_dir) # modify args to account for climate zones defined cz_csv_path = os.path.join(args['workspace_dir'], 'climate_zone_events.csv') make_climate_zone_csv(cz_csv_path) args['climate_zone_table_path'] = cz_csv_path cz_ras_path = os.path.join(args['workspace_dir'], 'dem.tif') make_gradient_raster(cz_ras_path) args['climate_zone_raster_path'] = cz_ras_path args['user_defined_climate_zones'] = True args['user_defined_local_recharge'] = False args['monthly_alpha'] = False args['results_suffix'] = 'cz' seasonal_water_yield.execute(args) # generate aggregated results csv table for assertion agg_results_csv_path = os.path.join(args['workspace_dir'], 'agg_results_cz.csv') make_agg_results_csv(agg_results_csv_path, climate_zones=True) SeasonalWaterYieldRegressionTests._assert_regression_results_equal( os.path.join(args['workspace_dir'], 'aggregated_results_swy_cz.shp'), agg_results_csv_path)
def test_base_regression(self): """SWY base regression test on sample data Executes SWY in default mode and checks that the output files are generated and that the aggregate shapefile fields are the same as the regression case.""" from natcap.invest.seasonal_water_yield import seasonal_water_yield # use predefined directory so test can clean up files during teardown args = SeasonalWaterYieldRegressionTests.generate_base_args( self.workspace_dir) # make args explicit that this is a base run of SWY args['user_defined_climate_zones'] = False args['user_defined_local_recharge'] = False args['monthly_alpha'] = False args['results_suffix'] = '' seasonal_water_yield.execute(args) SeasonalWaterYieldRegressionTests._assert_regression_results_equal( args['workspace_dir'], os.path.join(REGRESSION_DATA, 'file_list_base.txt'), os.path.join(args['workspace_dir'], 'aggregated_results.shp'), os.path.join(REGRESSION_DATA, 'agg_results_base.csv'))
args['k_param'] = '2' args['runoff_proxy_path'] = Pcp_Annual args['subsurface_critical_length_n'] = '1000' args['subsurface_critical_length_p'] = '1000' args['subsurface_eff_n'] = '0.5' args['subsurface_eff_p'] = '0.5' args['calc_sequestration'] = False args['carbon_pools_path'] = BioTable args['do_redd'] = False args['do_valuation'] = False args['lulc_cur_path'] = LULC # Seasonal Water Yield args['workspace_dir'] = os.path.join( os.path.split(os.getcwd())[0], 'RESULTS', '02-Seasonal-Water-Yield') swy.execute(args) # Anual Water Yield args['workspace_dir'] = os.path.join( os.path.split(os.getcwd())[0], 'RESULTS', '01-Anual-Water-Yield') awy.execute(args) # Sediment Delivery Ratio args['workspace_dir'] = os.path.join( os.path.split(os.getcwd())[0], 'RESULTS', '03-Sediment-Delivery-Ratio') sdr.execute(args) # Nutrient Delivery Ratio args['workspace_dir'] = os.path.join( os.path.split(os.getcwd())[0], 'RESULTS', '04-Nutrient-Delivery-Ratio') ndr.execute(args)
def test_base_regression_nodata_inf(self): """SWY base regression test on sample data with really small nodata. Executes SWY in default mode and checks that the output files are generated and that the aggregate shapefile fields are the same as the regression case. """ from natcap.invest.seasonal_water_yield import seasonal_water_yield # use predefined directory so test can clean up files during teardown args = SeasonalWaterYieldRegressionTests.generate_base_args( self.workspace_dir) # Ensure the model can pass when a nodata value is not defined. size = 100 lulc_array = numpy.zeros((size, size), dtype=numpy.int8) lulc_array[size // 2:, :] = 1 driver = gdal.GetDriverByName('GTiff') new_raster = driver.Create(args['lulc_raster_path'], lulc_array.shape[0], lulc_array.shape[1], 1, gdal.GDT_Byte) band = new_raster.GetRasterBand(1) band.WriteArray(lulc_array) geotransform = [1180000, 1, 0, 690000, 0, -1] new_raster.SetGeoTransform(geotransform) band = None new_raster = None driver = None # set precip nodata values to a large, negative 64bit value. nodata = numpy.finfo(numpy.float64).min precip_nodata_dir = os.path.join(self.workspace_dir, 'precip_nodata_dir') os.makedirs(precip_nodata_dir) size = 100 for month in range(1, 13): precip_raster_path = os.path.join( precip_nodata_dir, 'precip_mm_' + str(month) + '.tif') precip_array = numpy.full((size, size), month + 10, dtype=numpy.float64) precip_array[size - 1, :] = nodata srs = osr.SpatialReference() srs.ImportFromEPSG(26910) # UTM Zone 10N project_wkt = srs.ExportToWkt() # Each pixel is 1x1 m pygeoprocessing.numpy_array_to_raster(precip_array, nodata, (1, -1), (1180000, 690000), project_wkt, precip_raster_path) args['precip_dir'] = precip_nodata_dir # make args explicit that this is a base run of SWY args['user_defined_climate_zones'] = False args['user_defined_local_recharge'] = False args['monthly_alpha'] = False args['results_suffix'] = '' seasonal_water_yield.execute(args) # generate aggregated results csv table for assertion agg_results_csv_path = os.path.join(args['workspace_dir'], 'agg_results_base.csv') with open(agg_results_csv_path, 'w') as open_table: open_table.write('0,1.0,50.076062\n') SeasonalWaterYieldRegressionTests._assert_regression_results_equal( os.path.join(args['workspace_dir'], 'aggregated_results_swy.shp'), agg_results_csv_path)