Esempio n. 1
0
def Add_Inlets(Name_NC_Runoff, 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 wa.General.raster_conversions as RC
    import wa.Functions.Start.Area_converter as Area

    # Open information and open the Runoff array
    Runoff_dataCube = RC.Open_nc_array(Name_NC_Runoff)
    geo_out, epsg, size_X, size_Y, size_Z, Time = RC.Open_nc_info(
        Name_NC_Runoff)

    # 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][1:]
        Lat_coord = Coord[1][:-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_dataCube[time_step_array, lat_pix,
                                lon_pix] = Runoff_dataCube[time_step_array,
                                                           lat_pix,
                                                           lon_pix] + value_mm

    return (Runoff_dataCube)
Esempio n. 2
0
def Run(input_nc, output_nc):

    # Extract flow direction data from NetCDF file
    flow_directions = RC.Open_nc_array(input_nc, Var = 'demdir')

    # Open River Array
    Rivers = RC.Open_nc_array(output_nc, Var = 'rivers')

    # Open Accumulated Pixel Array
    Accumulated_Pixels = RC.Open_nc_array(output_nc, Var = 'accpix')

    # Open Routed discharge Array
    Routed_Array = RC.Open_nc_array(output_nc, Var = 'discharge_natural')

    # Get the raster shape
    geo_out_example, epsg_example, size_X_example, size_Y_example, size_Z_example, Time_example = RC.Open_nc_info(input_nc)
    geo_out_example = np.array(geo_out_example)

    # Create a river array with a boundary of 1 pixel
    Rivers_bounds = np.zeros([size_Y_example+2, size_X_example+2])
    Rivers_bounds[1:-1,1:-1] = Rivers

    # Create a flow direction array with a boundary of 1 pixel
    flow_directions[flow_directions==0]=-32768
    flow_directions_bound = np.ones([size_Y_example+2, size_X_example+2]) * -32768
    flow_directions_bound[1:-1,1:-1] = flow_directions

    # Create ID Matrix
    y,x = np.indices((size_Y_example, size_X_example))
    ID_Matrix = np.int32(np.ravel_multi_index(np.vstack((y.ravel(),x.ravel())),(size_Y_example,size_X_example),mode='clip').reshape(x.shape))
    ID_Matrix_bound = np.ones([size_Y_example+2, size_X_example+2]) * -32768
    ID_Matrix_bound[1:-1,1:-1] = ID_Matrix + 1
    ID_Matrix_bound[flow_directions_bound==-32768]=-32768
    del  x, y

    # Empty total from and to arrays
    ID_to_total=np.array([])
    ID_from_total=np.array([])

    # The flow directions parameters of HydroSHED
    Directions = [1, 2, 4, 8, 16, 32, 64, 128]

    # Loop over the directions
    for Direction in Directions:

        # empty from and to arrays for 1 direction
        data_flow_to = np.zeros([size_Y_example + 2, size_X_example + 2])
        data_flow_from = np.zeros([size_Y_example + 2, size_X_example + 2])

        # Get the ID of only the rivers
        data_flow_to_ID = np.zeros([size_Y_example + 2, size_X_example + 2])
        data_flow_in = np.ones([size_Y_example + 2, size_X_example + 2])	* Rivers_bounds

        # Mask only one direction
        data_flow_from[flow_directions_bound == Direction] = data_flow_in[flow_directions_bound == Direction] * ID_Matrix_bound[flow_directions_bound == Direction]

        # Add the data flow to ID
        if Direction == 4:
            data_flow_to[1:,:] = data_flow_from[:-1,:]
        if Direction == 2:
            data_flow_to[1:,1:] = data_flow_from[:-1,:-1]
        if Direction == 1:
            data_flow_to[:,1:] = data_flow_from[:,:-1]
        if Direction == 128:
            data_flow_to[:-1,1:] = data_flow_from[1:,:-1]
        if Direction == 64:
            data_flow_to[:-1,:] = data_flow_from[1:,:]
        if Direction == 32:
            data_flow_to[:-1,:-1] = data_flow_from[1:,1:]
        if Direction == 16:
            data_flow_to[:,:-1] = data_flow_from[:,1:]
        if Direction == 8:
            data_flow_to[1:,:-1] = data_flow_from[:-1,1:]

        # mask out the no river pixels
        data_flow_to_ID[data_flow_to>0] = ID_Matrix_bound[data_flow_to>0]

        # Collect to and from arrays
        ID_from_total = np.append(ID_from_total,data_flow_from[data_flow_from!=0].ravel())
        ID_to_total = np.append(ID_to_total,data_flow_to_ID[data_flow_to_ID!=0].ravel())


    ######################## Define the starting point ############################

    # Open Basin area
    Basin = RC.Open_nc_array(input_nc, Var = 'basin')
    Basin = -1 * (Basin - 1)
    Basin_Buffer = RC.Create_Buffer(Basin, 8)
    Possible_End_Points = np.zeros(Basin.shape)
    Possible_End_Points[(Basin_Buffer + Rivers) == 2] = 1
    End_Points = [[0,0]]

    rows_col_possible_end_pixels = np.argwhere(Possible_End_Points == 1)
    #  Accumulated_Pixels_possible = ID_Matrix * Possible_End_Points

    for PosPix in rows_col_possible_end_pixels:
        Accumulated_Pixels_possible_Area = Accumulated_Pixels[PosPix[0]-1:PosPix[0]+2, PosPix[1]-1:PosPix[1]+2]
        Max_acc_possible_area = np.max(Accumulated_Pixels_possible_Area)
        middle_pixel = Accumulated_Pixels_possible_Area[1,1]
        if Max_acc_possible_area == middle_pixel:
            if flow_directions[PosPix[0],PosPix[1]] == -32768:
                acc_aux = np.copy(Accumulated_Pixels_possible_Area)
                acc_aux[1,1] = 0
                off_y = np.where(acc_aux == np.max(acc_aux))[1][0] - 1
                off_x = np.where(acc_aux == np.max(acc_aux))[0][0] - 1
                PosPix[0] = PosPix[0] + off_x
                PosPix[1] = PosPix[1] + off_y
            if End_Points == []:
                End_Points = PosPix
            else:
                End_Points = np.vstack([End_Points, PosPix])

    # Create an empty dictionary for the rivers
    River_dict = dict()

    # Create empty array for the loop
    ID_starts_next = []
    i = 0

    for End_Point in End_Points[1:]:

    # Define starting point
    # Max_Acc_Pix = np.nanmax(Accumulated_Pixels[ID_Matrix_bound[1:-1,1:-1]>0])
    # ncol, nrow = np.argwhere(Accumulated_Pixels==Max_Acc_Pix)[0]

    # Add Bounds
    # col = ncol + 1
    # row = nrow + 1

        col = End_Point[0] + 1
        row = End_Point[1] + 1

        ############################ Route the river ##################################

        # Get the ID of the starting point
        ID_starts = [ID_Matrix_bound[col,row]]


        # Keep going on till all the branches are looped
        while len(ID_starts) > 0:
            for ID_start in ID_starts:
                ID_start = int(ID_start)

                # Empty parameters for new starting point
                new = 0
                IDs = []

                # Add starting point
                Arrays_from = np.argwhere(ID_from_total[:] == ID_start)
                ID_from = ID_to_total[int(Arrays_from[0])]
                IDs = np.array([ID_from, ID_start])
                ID_start_now = ID_start

                # Keep going till the branch ends
                while new == 0:

                    Arrays_to = np.argwhere(ID_to_total[:] == ID_start)

                    # Add IDs to the river dictionary
                    if len(Arrays_to)>1 or len(Arrays_to) == 0:
                        River_dict[i] = IDs
                        i += 1
                        new = 1

                        # Define the next loop for the new branches
                        for j in range(0, len(Arrays_to)):
                            ID_starts_next = np.append(ID_starts_next,ID_from_total[int(Arrays_to[j])])

                        # If it was the last one then empty ID_start_next
                        if ID_start_now == ID_starts[-1]:
                            ID_starts = ID_starts_next
                            ID_starts_next = []

                    # Add pixel to tree for river dictionary
                    else:
                        ID_start = ID_from_total[Arrays_to[0]]
                        IDs = np.append(IDs, ID_start)

    ######################## Create dict distance and dict dem ####################

    # Extract DEM data from NetCDF file
    DEM = RC.Open_nc_array(input_nc, Var = 'dem')

    # Get the distance of a horizontal and vertical flow pixel (assuming it flows in a straight line)
    import wa.Functions.Start.Area_converter as AC
    vertical, horizontal = AC.Calc_dlat_dlon(geo_out_example,size_X_example, size_Y_example)

    # Calculate a diagonal flowing pixel (assuming it flos in a straight line)
    diagonal = np.power((np.square(vertical) + np.square(horizontal)),0.5)

    # Create empty distance array
    Distance = np.zeros([size_Y_example, size_X_example])

    # Fill in the distance array
    Distance[np.logical_or(flow_directions == 1,flow_directions == 16)] = horizontal[np.logical_or(flow_directions == 1,flow_directions == 16)]
    Distance[np.logical_or(flow_directions == 64,flow_directions == 4)] = vertical[np.logical_or(flow_directions == 64,flow_directions == 4)]
    Distance[np.logical_or(np.logical_or(np.logical_or(flow_directions == 32,flow_directions == 8),flow_directions == 128),flow_directions == 2)] = diagonal[np.logical_or(np.logical_or(np.logical_or(flow_directions == 32,flow_directions == 8),flow_directions == 128),flow_directions == 2)]

    # Create empty dicionaries for discharge, distance, and DEM
    Discharge_dict = dict()
    Distance_dict = dict()
    DEM_dict = dict()

    # Create empty arrays needed for the loop
    River_end = []
    River_ends = np.zeros([2,3])


    # Loop over the branches
    for River_number in range(0,len(River_dict)):

        # Get the pixels associated with the river section
        River = River_dict[River_number]
        i=1

        # Create empty arrays
        Distances_river = np.zeros([len(River)])
        DEM_river = np.zeros([len(River)])
        Discharge_river = np.zeros([len(River)])

        # for the first pixel get the previous pixel value from another branche
        row_start = np.argwhere(River_ends[:,0] == River[0])
        if len(row_start) < 1:
            Distances_river[0] = 0
            row, col = np.argwhere(ID_Matrix_bound == River[0])[0][:]
            DEM_river[0] = DEM[row - 1, col - 1]
            Discharge_river[0] = -9999

        else:
            Distances_river[0] = River_ends[row_start, 1]
            DEM_river[0] = River_ends[row_start, 2]
            row, col = np.argwhere(ID_Matrix_bound == River[0])[0][:]
            #Discharge_river[0] = Routed_Discharge[timestep, row - 1, col - 1]

        # For the other pixels get the value of the River ID pixel
        for River_part in River[1:]:
            row, col = np.argwhere(ID_Matrix_bound == River_part)[0][:]
            Distances_river[i] = Distance[row - 1, col - 1]
            DEM_river[i] = np.max([DEM_river[i-1],DEM[row - 1, col - 1]])
            #Discharge_river[i] = Routed_Discharge[timestep, row - 1, col - 1]

            if River_part == River[1] and Discharge_river[i-1] == -9999:
                Discharge_river[i - 1] = Discharge_river[i]

            i += 1

        # Write array in dictionary
        DEM_dict[River_number] = DEM_river
        Discharge_dict[River_number] = Discharge_river
        Distance_dict[River_number] = np.cumsum(Distances_river)

        # Save the last pixel value
        River_end[:] = [River_part , np.cumsum(Distances_river)[-1], DEM_river[-1]]
        River_ends = np.vstack((River_ends, River_end))


    ########################## Discharge Dictionary ###############################

    # Create ID Matrix
    y,x = np.indices((size_Y_example, size_X_example))
    ID_Matrix = np.int32(np.ravel_multi_index(np.vstack((y.ravel(),x.ravel())),(size_Y_example,size_X_example),mode='clip').reshape(x.shape))
    ID_Matrix_bound = np.ones([size_Y_example+2, size_X_example+2]) * -32768
    ID_Matrix_bound[1:-1,1:-1] = ID_Matrix + 1
    del  x, y

    # Create empty dicionaries for discharge, distance, and DEM
    Discharge_dict = dict()

    Amount_months = len(RC.Open_nc_array(input_nc, Var = 'time'))

    # Loop over the branches
    for River_number in range(0,len(River_dict)):

        # Get the pixels associated with the river section
        River = River_dict[River_number]
        i=0

        # Create empty arrays
        Discharge_river = np.zeros([Amount_months, len(River)])

        # For the other pixels get the value of the River ID pixel
        for River_part in River[:]:
            row, col = np.argwhere(ID_Matrix_bound == River_part)[0][:]
            Discharge_river[:,i] = Routed_Array[:, row - 1, col - 1]
            i += 1

        # Write array in dictionary
        Discharge_dict[River_number] = Discharge_river
        print(River_number)

    return(DEM_dict, River_dict, Distance_dict, Discharge_dict)
Esempio n. 3
0
def Find_Area_Volume_Relation(region, input_JRC, DEM_dataset):

    # Find relation between V and A

    import numpy as np
    import wa.General.raster_conversions as RC
    import wa.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

    # Save Example as memory file
    dest_example = DC.Save_as_MEM(Water_array, Geo_out, projection='WGS84')

    # reproject DEM by using example
    dest_out = RC.reproject_dataset_example(DEM_dataset,
                                            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 wa.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)
Esempio n. 4
0
def Rivers_General(Name_NC_DEM, Name_NC_DEM_Dir, Name_NC_Acc_Pixels, Name_NC_Rivers, Reference_data):

    import numpy as np
    from wa.General import raster_conversions as RC
    
    ############################### Open needed dataset ###########################
    
    # Extract flow direction data from NetCDF file
    flow_directions = RC.Open_nc_array(Name_NC_DEM_Dir)
     
    # Extract Rivers data from NetCDF file
    Rivers = RC.Open_nc_array(Name_NC_Rivers)

    # Extract DEM data from NetCDF file
    DEM = RC.Open_nc_array(Name_NC_DEM) 

    # Extract Accumulated pixels data from NetCDF file
    Accumulated_Pixels = RC.Open_nc_array(Name_NC_Acc_Pixels) 
			
    ############################### Create river tree #############################
        
    # Get the raster shape	
    size_Y, size_X = np.shape(flow_directions)
    
    # Create a river array with a boundary of 1 pixel
    Rivers_bounds = np.zeros([size_Y+2, size_X+2])
    Rivers_bounds[1:-1,1:-1] = Rivers	
    
    # Create a flow direction array with a boundary of 1 pixel
    flow_directions[flow_directions==0]=-32768
    flow_directions_bound = np.ones([size_Y+2, size_X+2]) * -32768
    flow_directions_bound[1:-1,1:-1] = flow_directions
    
    # 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))
    ID_Matrix_bound = np.ones([size_Y+2, size_X+2]) * -32768
    ID_Matrix_bound[1:-1,1:-1] = ID_Matrix + 1
    ID_Matrix_bound[flow_directions_bound==-32768]=-32768
    del  x, y
    
    # Empty total from and to arrays
    ID_to_total=np.array([])
    ID_from_total=np.array([])
    
    # The flow directions parameters of HydroSHED
    Directions = [1, 2, 4, 8, 16, 32, 64, 128]
    
    # Loop over the directions			
    for Direction in Directions:
    
        # empty from and to arrays for 1 direction				
        data_flow_to = np.zeros([size_Y + 2, size_X + 2])
        data_flow_from = np.zeros([size_Y + 2, size_X + 2])
    				
        # Get the ID of only the rivers
        data_flow_to_ID = np.zeros([size_Y + 2, size_X + 2])			
        data_flow_in = np.ones([size_Y + 2, size_X + 2])	* Rivers_bounds	
    				
        # Mask only one direction				
        data_flow_from[flow_directions_bound == Direction] = data_flow_in[flow_directions_bound == Direction] * ID_Matrix_bound[flow_directions_bound == Direction]
    
        # Add the data flow to ID  
        if Direction == 4:
            data_flow_to[1:,:] = data_flow_from[:-1,:]
        if Direction == 2:
            data_flow_to[1:,1:] = data_flow_from[:-1,:-1]
        if Direction == 1:
            data_flow_to[:,1:] = data_flow_from[:,:-1]
        if Direction == 128:
            data_flow_to[:-1,1:] = data_flow_from[1:,:-1]
        if Direction == 64:
            data_flow_to[:-1,:] = data_flow_from[1:,:]
        if Direction == 32:
            data_flow_to[:-1,:-1] = data_flow_from[1:,1:]
        if Direction == 16:
            data_flow_to[:,:-1] = data_flow_from[:,1:]
        if Direction == 8:
            data_flow_to[1:,:-1] = data_flow_from[:-1,1:]
    
        # mask out the no river pixels
        data_flow_to_ID[data_flow_to>0] = ID_Matrix_bound[data_flow_to>0]
    
        # Collect to and from arrays
        ID_from_total = np.append(ID_from_total,data_flow_from[data_flow_from!=0].ravel())		
        ID_to_total = np.append(ID_to_total,data_flow_to_ID[data_flow_to_ID!=0].ravel())				
    
    
    ######################## Define the starting point ############################
    
    # Define starting point
    Max_Acc_Pix = np.nanmax(Accumulated_Pixels[ID_Matrix_bound[1:-1,1:-1]>0])
    ncol, nrow = np.argwhere(Accumulated_Pixels==Max_Acc_Pix)[0]  				

    # Add Bounds				
    col = ncol + 1
    row = nrow + 1
    
    ############################ Route the river ##################################
    
    # Get the ID of the starting point
    ID_starts = [ID_Matrix_bound[col,row]]
    
    # Create an empty dictionary for the rivers
    River_dict = dict()
    
    # Create empty array for the loop
    ID_starts_next = []	
    i = 0  
    
    # Keep going on till all the branches are looped
    while len(ID_starts) > 0:
        for ID_start in ID_starts:
            ID_start = int(ID_start)
    								
            # Empty parameters for new starting point								
            new = 0
            IDs = []	
    								
            # Add starting point								
            Arrays_from = np.argwhere(ID_from_total[:] == ID_start)             
            ID_from = ID_to_total[int(Arrays_from[0])]							
            IDs = [ID_from, ID_start]
            ID_start_now = ID_start	
    
            # Keep going till the branch ends								
            while new == 0:					
     
                Arrays_to = np.argwhere(ID_to_total[:] == ID_start)
    
                # Add IDs to the river dictionary
                if len(Arrays_to)>1 or len(Arrays_to) == 0:
                    River_dict[i] = IDs
                    i += 1	
                    new = 1
     
                    # Define the next loop for the new branches             											
                    for j in range(0, len(Arrays_to)):													
                        ID_starts_next = np.append(ID_starts_next,ID_from_total[int(Arrays_to[j])])												
    
                    # If it was the last one then empty ID_start_next                               																								
                    if ID_start_now == ID_starts[-1]:
                        ID_starts = ID_starts_next
                        ID_starts_next = []	
    
                # Add pixel to tree for river dictionary						
                else:
                    ID_start = ID_from_total[Arrays_to[0]]						
                    IDs = np.append(IDs, ID_start)									
         
									
    ######################## Create dict distance and dict dem ####################							
    # Get raster information 
    geo_out, proj, size_X, size_Y = RC.Open_array_info(Reference_data)
    # Get the distance of a horizontal and vertical flow pixel (assuming it flows in a straight line)
    import wa.Functions.Start.Area_converter as AC
    vertical, horizontal = AC.Calc_dlat_dlon(geo_out,size_X, size_Y)
    
    # Calculate a diagonal flowing pixel (assuming it flos in a straight line)
    diagonal = np.power((np.square(vertical) + np.square(horizontal)),0.5)
    
    # Create empty distance array
    Distance = np.zeros([size_Y, size_X])
    
    # Fill in the distance array
    Distance[np.logical_or(flow_directions == 1,flow_directions == 16)] = horizontal[np.logical_or(flow_directions == 1,flow_directions == 16)]
    Distance[np.logical_or(flow_directions == 64,flow_directions == 4)] = vertical[np.logical_or(flow_directions == 64,flow_directions == 4)]
    Distance[np.logical_or(np.logical_or(np.logical_or(flow_directions == 32,flow_directions == 8),flow_directions == 128),flow_directions == 2)] = diagonal[np.logical_or(np.logical_or(np.logical_or(flow_directions == 32,flow_directions == 8),flow_directions == 128),flow_directions == 2)]						
    
    # Create empty dicionaries for discharge, distance, and DEM
    Discharge_dict = dict()
    Distance_dict = dict()
    DEM_dict = dict()
        
    # Create empty arrays needed for the loop
    River_end = []
    River_ends = np.zeros([2,3])
    
    # Loop over the branches
    for River_number in range(0,len(River_dict)):
	    
        # Get the pixels associated with the river section    
        River = River_dict[River_number]
        i=1	
	    			
        # Create empty arrays				
        Distances_river = np.zeros([len(River)])
        DEM_river = np.zeros([len(River)])	
        Discharge_river = np.zeros([len(River)])	
        
        # for the first pixel get the previous pixel value from another branche				
        row_start = np.argwhere(River_ends[:,0] == River[0])	
        if len(row_start) < 1:			
            Distances_river[0] = 0
            row, col = np.argwhere(ID_Matrix_bound == River[0])[0][:]
            DEM_river[0] = DEM[row - 1, col - 1] 
            Discharge_river[0] = -9999        
					
        else:
            Distances_river[0] = River_ends[row_start, 1]
            DEM_river[0] = River_ends[row_start, 2]
            row, col = np.argwhere(ID_Matrix_bound == River[0])[0][:]
            #Discharge_river[0] = Routed_Discharge[timestep, row - 1, col - 1] 	

        # For the other pixels get the value of the River ID pixel								
        for River_part in River[1:]:
            row, col = np.argwhere(ID_Matrix_bound == River_part)[0][:]
            Distances_river[i] = Distance[row - 1, col - 1]						
            DEM_river[i] = np.max([DEM_river[i-1],DEM[row - 1, col - 1]])  
            #Discharge_river[i] = Routed_Discharge[timestep, row - 1, col - 1]								
    
            if River_part == River[1] and Discharge_river[i-1] == -9999:
                Discharge_river[i - 1] = Discharge_river[i]         
  													
            i += 1

        # Write array in dictionary													
        DEM_dict[River_number] = DEM_river
        Discharge_dict[River_number] = Discharge_river 
        Distance_dict[River_number] = np.cumsum(Distances_river)
				
        # Save the last pixel value				
        River_end[:] = [River_part , np.cumsum(Distances_river)[-1], DEM_river[-1]]								
        River_ends = np.vstack((River_ends, River_end))	

    return(River_dict, DEM_dict, Distance_dict)