def run(input_nc, Inflow_Text_Files): ''' This functions add inflow to the runoff dataset before the channel routing. The inflow must be a text file with a certain format. The first line of this format are the latitude and longitude. Hereafter for each line the time (ordinal time) and the inflow (m3/month) seperated with one space is defined. See example below: lat lon 733042 156225.12 733073 32511321.2 733102 212315.25 733133 2313266.554 ''' # General modules import numpy as np # Water Accounting modules import watools.General.raster_conversions as RC import watools.Functions.Start.Area_converter as Area Runoff = RC.Open_nc_array(input_nc, Var='Runoff_M') # Open information and open the Runoff array geo_out, epsg, size_X, size_Y, size_Z, Time = RC.Open_nc_info(input_nc) # Calculate the surface area of every pixel dlat, dlon = Area.Calc_dlat_dlon(geo_out, size_X, size_Y) area_in_m2 = dlat * dlon for Inflow_Text_File in Inflow_Text_Files: # Open the inlet text data Inlet = np.genfromtxt(Inflow_Text_File, dtype=None, delimiter=" ") # Read out the coordinates Coord = Inlet[0, :] Lon_coord = Coord[0] Lat_coord = Coord[1] # Search for the pixel lon_pix = int(np.ceil((float(Lon_coord) - geo_out[0]) / geo_out[1])) lat_pix = int(np.ceil((float(Lat_coord) - geo_out[3]) / geo_out[5])) # Add the value on top of the Runoff array for i in range(1, len(Inlet)): time = float(Inlet[i, 0]) time_step = np.argwhere(np.logical_and(Time >= time, Time <= time)) if len(time_step) > 0: time_step_array = int(time_step[0][0]) value_m3_month = float(Inlet[i, 1]) area_in_m2_pixel = area_in_m2[lat_pix, lon_pix] value_mm = (value_m3_month / area_in_m2_pixel) * 1000 Runoff[time_step_array, lat_pix, lon_pix] = Runoff[time_step_array, lat_pix, lon_pix] + value_mm return (Runoff)
def Degrees_to_m2(Reference_data): """ This functions calculated the area of each pixel in squared meter. Parameters ---------- Reference_data: str Path to a tiff file or nc file or memory file of which the pixel area must be defined Returns ------- area_in_m2: array Array containing the area of each pixel in squared meters """ try: # Get the extension of the example data filename, file_extension = os.path.splitext(Reference_data) # Get raster information if str(file_extension) == '.tif': geo_out, proj, size_X, size_Y = RC.Open_array_info(Reference_data) elif str(file_extension) == '.nc': geo_out, epsg, size_X, size_Y, size_Z, Time = RC.Open_nc_info( Reference_data) except: geo_out = Reference_data.GetGeoTransform() size_X = Reference_data.RasterXSize() size_Y = Reference_data.RasterYSize() # Calculate the difference in latitude and longitude in meters dlat, dlon = Calc_dlat_dlon(geo_out, size_X, size_Y) # Calculate the area in squared meters area_in_m2 = dlat * dlon return (area_in_m2)
def Add_Reservoirs(output_nc, Diff_Water_Volume, Regions): import numpy as np import watools.General.raster_conversions as RC import watools.General.data_conversions as DC # Extract data from NetCDF file Discharge_dict = RC.Open_nc_dict(output_nc, "dischargedict_dynamic") River_dict = RC.Open_nc_dict(output_nc, "riverdict_static") DEM_dict = RC.Open_nc_dict(output_nc, "demdict_static") Distance_dict = RC.Open_nc_dict(output_nc, "distancedict_static") Rivers = RC.Open_nc_array(output_nc, "rivers") acc_pixels = RC.Open_nc_array(output_nc, "accpix") # Open data array info based on example data geo_out, epsg, size_X, size_Y, size_Z, time = RC.Open_nc_info(output_nc) # Create ID Matrix y, x = np.indices((size_Y, size_X)) ID_Matrix = np.int32( np.ravel_multi_index(np.vstack((y.ravel(), x.ravel())), (size_Y, size_X), mode='clip').reshape(x.shape)) + 1 del x, y Acc_Pixels_Rivers = Rivers * acc_pixels ID_Rivers = Rivers * ID_Matrix Amount_of_Reservoirs = len(Regions) Reservoir_is_in_River = np.ones([len(Regions), 3]) * -9999 for reservoir in range(0, Amount_of_Reservoirs): region = Regions[reservoir, :] dest = DC.Save_as_MEM(Acc_Pixels_Rivers, geo_out, projection='WGS84') Rivers_Acc_Pixels_reservoir, Geo_out = RC.clip_data( dest, latlim=[region[2], region[3]], lonlim=[region[0], region[1]]) dest = DC.Save_as_MEM(ID_Rivers, geo_out, projection='WGS84') Rivers_ID_reservoir, Geo_out = RC.clip_data( dest, latlim=[region[2], region[3]], lonlim=[region[0], region[1]]) size_Y_reservoir, size_X_reservoir = np.shape( Rivers_Acc_Pixels_reservoir) IDs_Edges = [] IDs_Edges = np.append(IDs_Edges, Rivers_Acc_Pixels_reservoir[0, :]) IDs_Edges = np.append(IDs_Edges, Rivers_Acc_Pixels_reservoir[:, 0]) IDs_Edges = np.append( IDs_Edges, Rivers_Acc_Pixels_reservoir[int(size_Y_reservoir) - 1, :]) IDs_Edges = np.append( IDs_Edges, Rivers_Acc_Pixels_reservoir[:, int(size_X_reservoir) - 1]) Value_Reservoir = np.max(np.unique(IDs_Edges)) y_pix_res, x_pix_res = np.argwhere( Rivers_Acc_Pixels_reservoir == Value_Reservoir)[0] ID_reservoir = Rivers_ID_reservoir[y_pix_res, x_pix_res] # Find exact reservoir area in river directory for River_part in River_dict.items(): if len(np.argwhere(River_part[1] == ID_reservoir)) > 0: Reservoir_is_in_River[reservoir, 0] = np.argwhere( River_part[1] == ID_reservoir) #River_part_good Reservoir_is_in_River[reservoir, 1] = River_part[0] #River_Add_Reservoir Reservoir_is_in_River[reservoir, 2] = 1 #Reservoir_is_in_River numbers = abs(Reservoir_is_in_River[:, 1].argsort() - len(Reservoir_is_in_River) + 1) for number in range(0, len(Reservoir_is_in_River)): row_reservoir = np.argwhere(numbers == number)[0][0] if not Reservoir_is_in_River[row_reservoir, 2] == -9999: # Get discharge into the reservoir: Flow_in_res_m3 = Discharge_dict[int(Reservoir_is_in_River[ row_reservoir, 1])][:, int(Reservoir_is_in_River[row_reservoir, 0])] # Get difference reservoir Change_Reservoir_m3 = Diff_Water_Volume[row_reservoir, :, 2] # Total Change outflow Change_outflow_m3 = np.minimum(Flow_in_res_m3, Change_Reservoir_m3) Difference = Change_outflow_m3 - Change_Reservoir_m3 if abs(np.sum(Difference)) > 10000 and np.sum( Change_Reservoir_m3[Change_outflow_m3 > 0]) > 0: Change_outflow_m3[Change_outflow_m3 < 0] = Change_outflow_m3[ Change_outflow_m3 < 0] * np.sum( Change_outflow_m3[Change_outflow_m3 > 0]) / np.sum( Change_Reservoir_m3[Change_outflow_m3 > 0]) # Find key name (which is also the lenght of the river dictionary) i = len(River_dict) #River_with_reservoirs_dict[i]=list((River_dict[River_Add_Reservoir][River_part_good[0][0]:]).flat) < MAAK DIRECTORIES ARRAYS OP DEZE MANIER DAN IS DE ARRAY 1D River_dict[i] = River_dict[int(Reservoir_is_in_River[ row_reservoir, 1])][int(Reservoir_is_in_River[row_reservoir, 0]):] River_dict[int( Reservoir_is_in_River[row_reservoir, 1])] = River_dict[int( Reservoir_is_in_River[ row_reservoir, 1])][:int(Reservoir_is_in_River[row_reservoir, 0]) + 1] DEM_dict[i] = DEM_dict[int(Reservoir_is_in_River[ row_reservoir, 1])][int(Reservoir_is_in_River[row_reservoir, 0]):] DEM_dict[int( Reservoir_is_in_River[row_reservoir, 1])] = DEM_dict[int( Reservoir_is_in_River[ row_reservoir, 1])][:int(Reservoir_is_in_River[row_reservoir, 0]) + 1] Distance_dict[i] = Distance_dict[int(Reservoir_is_in_River[ row_reservoir, 1])][int(Reservoir_is_in_River[row_reservoir, 0]):] Distance_dict[int( Reservoir_is_in_River[row_reservoir, 1])] = Distance_dict[int( Reservoir_is_in_River[ row_reservoir, 1])][:int(Reservoir_is_in_River[row_reservoir, 0]) + 1] Discharge_dict[i] = Discharge_dict[int(Reservoir_is_in_River[ row_reservoir, 1])][:, int(Reservoir_is_in_River[row_reservoir, 0]):] Discharge_dict[int( Reservoir_is_in_River[row_reservoir, 1])] = Discharge_dict[int( Reservoir_is_in_River[ row_reservoir, 1])][:, :int(Reservoir_is_in_River[row_reservoir, 0]) + 1] Discharge_dict[int(Reservoir_is_in_River[ row_reservoir, 1])][:, 1:int(Reservoir_is_in_River[row_reservoir, 0]) + 1] = Discharge_dict[int( Reservoir_is_in_River[row_reservoir, 1] )][:, 1:int(Reservoir_is_in_River[row_reservoir, 0]) + 1] - Change_outflow_m3[:, None] Next_ID = River_dict[int(Reservoir_is_in_River[row_reservoir, 1])][0] times = 0 while len(River_dict) > times: for River_part in River_dict.items(): if River_part[-1][-1] == Next_ID: Next_ID = River_part[-1][0] item = River_part[0] #Always 10 procent of the incoming discharge will pass the dam Change_outflow_m3[:, None] = np.minimum( 0.9 * Discharge_dict[item][:, -1:], Change_outflow_m3[:, None]) Discharge_dict[item][:, 1:] = Discharge_dict[ item][:, 1:] - Change_outflow_m3[:, None] print(item) times = 0 times += 1 return (Discharge_dict, River_dict, DEM_dict, Distance_dict)
def Find_Area_Volume_Relation(region, input_JRC, input_nc): # Find relation between V and A import numpy as np import watools.General.raster_conversions as RC import watools.General.data_conversions as DC from scipy.optimize import curve_fit import matplotlib.pyplot as plt def func(x, a, b): """ This function is used for finding relation area and volume """ return (a * x**b) def func3(x, a, b, c, d): """ This function is used for finding relation area and volume """ return (a * (x - c)**b + d) #Array, Geo_out = RC.clip_data(input_JRC,latlim=[14.528,14.985],lonlim =[35.810,36.005]) Array, Geo_out = RC.clip_data( input_JRC, latlim=[region[2], region[3]], lonlim=[region[0], region[1] ]) # This reservoir was not filled when SRTM was taken size_Y = int(np.shape([Array])[-2]) size_X = int(np.shape([Array])[-1]) Water_array = np.zeros(np.shape(Array)) buffer_zone = 4 Array[Array > 0] = 1 for i in range(0, size_Y): for j in range(0, size_X): Water_array[i, j] = np.max(Array[ np.maximum(0, i - buffer_zone):np.minimum(size_Y, i + buffer_zone + 1), np.maximum(0, j - buffer_zone):np.minimum(size_X, j + buffer_zone + 1)]) del Array # Open DEM and reproject DEM_Array = RC.Open_nc_array(input_nc, "dem") Geo_out_dem, proj_dem, size_X_dem, size_Y_dem, size_Z_dem, time = RC.Open_nc_info( input_nc) # Save Example as memory file dest_example = DC.Save_as_MEM(Water_array, Geo_out, projection='WGS84') dest_dem = DC.Save_as_MEM(DEM_Array, Geo_out_dem, projection='WGS84') # reproject DEM by using example dest_out = RC.reproject_dataset_example(dest_dem, dest_example, method=2) DEM = dest_out.GetRasterBand(1).ReadAsArray() # find DEM water heights DEM_water = np.zeros(np.shape(Water_array)) DEM_water[Water_array != 1] = np.nan DEM_water[Water_array == 1.] = DEM[Water_array == 1.] # Get array with areas import watools.Functions.Start.Area_converter as Area dlat, dlon = Area.Calc_dlat_dlon(Geo_out, size_X, size_Y) area_in_m2 = dlat * dlon # find volume and Area min_DEM_water = int(np.round(np.nanmin(DEM_water))) max_DEM_water = int(np.round(np.nanmax(DEM_water))) Reservoir_characteristics = np.zeros([1, 5]) i = 0 for height in range(min_DEM_water + 1, max_DEM_water): DEM_water_below_height = np.zeros(np.shape(DEM_water)) DEM_water[np.isnan(DEM_water)] = 1000000 DEM_water_below_height[DEM_water < height] = 1 pixels = np.sum(DEM_water_below_height) area = np.sum(DEM_water_below_height * area_in_m2) if height == min_DEM_water + 1: volume = 0.5 * area histogram = pixels Reservoir_characteristics[:] = [ height, pixels, area, volume, histogram ] else: area_previous = Reservoir_characteristics[i, 2] volume_previous = Reservoir_characteristics[i, 3] volume = volume_previous + 0.5 * ( area - area_previous) + 1 * area_previous histogram_previous = Reservoir_characteristics[i, 1] histogram = pixels - histogram_previous Reservoir_characteristics_one = [ height, pixels, area, volume, histogram ] Reservoir_characteristics = np.append( Reservoir_characteristics, Reservoir_characteristics_one) i += 1 Reservoir_characteristics = np.resize(Reservoir_characteristics, (i + 1, 5)) maxi = int(len(Reservoir_characteristics[:, 3])) # find minimum value for reservoirs height (DEM is same value if reservoir was already filled whe SRTM was created) Historgram = Reservoir_characteristics[:, 4] hist_mean = np.mean(Historgram) hist_std = np.std(Historgram) mini_tresh = hist_std * 5 + hist_mean Check_hist = np.zeros([len(Historgram)]) Check_hist[Historgram > mini_tresh] = Historgram[Historgram > mini_tresh] if np.max(Check_hist) != 0.0: col = np.argwhere(Historgram == np.max(Check_hist))[0][0] mini = col + 1 else: mini = 0 fitted = 0 # find starting point reservoirs V0 = Reservoir_characteristics[mini, 3] A0 = Reservoir_characteristics[mini, 2] # Calculate the best maxi reservoir characteristics, based on the normal V = a*x**b relation while fitted == 0: try: if mini == 0: popt1, pcov1 = curve_fit( func, Reservoir_characteristics[mini:maxi, 2], Reservoir_characteristics[mini:maxi, 3]) else: popt1, pcov1 = curve_fit( func, Reservoir_characteristics[mini:maxi, 2] - A0, Reservoir_characteristics[mini:maxi, 3] - V0) fitted = 1 except: maxi -= 1 if maxi < mini: print('ERROR: was not able to find optimal fit') fitted = 1 # Remove last couple of pixels of maxi maxi_end = int(np.round(maxi - 0.2 * (maxi - mini))) done = 0 times = 0 while done == 0 and times > 20 and maxi_end < mini: try: if mini == 0: popt, pcov = curve_fit( func, Reservoir_characteristics[mini:maxi_end, 2], Reservoir_characteristics[mini:maxi_end, 3]) else: popt, pcov = curve_fit( func3, Reservoir_characteristics[mini:maxi_end, 2], Reservoir_characteristics[mini:maxi_end, 3]) except: maxi_end = int(maxi) if mini == 0: popt, pcov = curve_fit( func, Reservoir_characteristics[mini:maxi_end, 2], Reservoir_characteristics[mini:maxi_end, 3]) else: popt, pcov = curve_fit( func3, Reservoir_characteristics[mini:maxi_end, 2], Reservoir_characteristics[mini:maxi_end, 3]) if mini == 0: plt.plot(Reservoir_characteristics[mini:maxi_end, 2], Reservoir_characteristics[mini:maxi_end, 3], 'ro') t = np.arange(0., np.max(Reservoir_characteristics[:, 2]), 1000) plt.plot(t, popt[0] * (t)**popt[1], 'g--') plt.axis([ 0, np.max(Reservoir_characteristics[mini:maxi_end, 2]), 0, np.max(Reservoir_characteristics[mini:maxi_end, 3]) ]) plt.show() done = 1 else: plt.plot(Reservoir_characteristics[mini:maxi_end, 2], Reservoir_characteristics[mini:maxi_end, 3], 'ro') t = np.arange(0., np.max(Reservoir_characteristics[:, 2]), 1000) plt.plot(t, popt[0] * (t - popt[2])**popt[1] + popt[3], 'g--') plt.axis([ 0, np.max(Reservoir_characteristics[mini:maxi_end, 2]), 0, np.max(Reservoir_characteristics[mini:maxi_end, 3]) ]) plt.show() Volume_error = popt[3] / V0 * 100 - 100 print('error Volume = %s percent' % Volume_error) print('error Area = %s percent' % (A0 / popt[2] * 100 - 100)) if Volume_error < 30 and Volume_error > -30: done = 1 else: times += 1 maxi_end -= 1 print('Another run is done in order to improve the result') if done == 0: popt = np.append(popt1, [A0, V0]) if len(popt) == 2: popt = np.append(popt, [0, 0]) return (popt)