Exemple #1
0
def RunLumpedRRP(ConceptualModel,
                 Raster,
                 sp_prec,
                 sp_et,
                 sp_temp,
                 sp_pars,
                 p2,
                 snow,
                 init_st=None,
                 ll_temp=None,
                 q_init=None):
    """
    ========================================================================
      RunLumpedRRP(Raster,sp_prec,sp_et,sp_temp,sp_pars,p2,init_st,ll_temp,q_init)
    ========================================================================

    this function runs the rainfall runoff lumped model (HBV, GR4,...) separately
    for each cell and return a time series of arrays

    Inputs:
    ----------
        1-ConceptualModel:
            [function] conceptual model function
        2-Raster:
            [gdal.dataset] raster to get the spatial information (nodata cells)
            raster input could be dem, flow accumulation or flow direction raster of the catchment
            but the nodata value stored in the raster should be far from the
            range of values that could result from the calculation
        3-sp_prec:
            [numpy array] 3d array of the precipitation data, sp_prec should
            have the same 2d dimension of raster input
        4-sp_et:
            [numpy array] 3d array of the evapotranspiration data, sp_et should
            have the same 2d dimension of raster input
        5-sp_temp:
            [numpy array] 3d array of the temperature data, sp_temp should
            have the same 2d dimension of raster input
        6-sp_pars:
            [numpy array] number of 2d arrays of the catchment properties spatially
            distributed in 2d and the third dimension is the number of parameters,
            sp_pars should have the same 2d dimension of raster input
        7-p2:
            [List] list of unoptimized parameters
            p2[0] = tfac, 1 for hourly, 0.25 for 15 min time step and 24 for daily time step
            p2[1] = catchment area in km2
        8-init_st:
            [list] initial state variables values [sp, sm, uz, lz, wc]. default=None
        9-ll_temp:
            [numpy array] 3d array of the long term average temperature data
        10-q_init:
            [float] initial discharge m3/s
    Outputs:
    ----------
        1-st:
            [numpy ndarray] 4D array (rows,cols,time,states) states are [sp,wc,sm,uz,lv]
        2-q_lz:
            [numpy ndarray] 3D array of the lower zone discharge
        3-q_uz:
            [numpy ndarray] 3D array of the upper zone discharge
    Example:
    ----------
        ### meteorological data
        prec=GIS.ReadRastersFolder(PrecPath)
        evap=GIS.ReadRastersFolder(Evap_Path)
        temp=GIS.ReadRastersFolder(TempPath)
        sp_pars=GIS.ReadRastersFolder(parPath)

        #### GIS data
        dem= gdal.Open(DemPath)

        p2=[1, 227.31]
        init_st=[0,5,5,5,0]

        st, q_lz, q_uz = DistRRM.RunLumpedRRP(DEM,sp_prec=sp_prec, sp_et=sp_et,
                               sp_temp=sp_temp, sp_pars=sp_par, p2=p2,
                               init_st=init_st)
    """
    ### input data validation
    # data type
    assert isinstance(
        ConceptualModel, ModuleType
    ), "ConceptualModel should be a module or a python file contains functions "
    assert type(
        Raster
    ) == gdal.Dataset, "Raster should be read using gdal (gdal dataset please read it using gdal library) "
    assert type(sp_prec) == np.ndarray, "array should be of type numpy array"
    assert type(sp_et) == np.ndarray, "array should be of type numpy array"
    assert type(sp_temp) == np.ndarray, "array should be of type numpy array"
    assert type(sp_pars) == np.ndarray, "array should be of type numpy array"
    assert type(p2) == list, "p2 should be of type list"

    if init_st != None:
        assert type(init_st) == list, "init_st should be of type list"
    if ll_temp != None:
        assert type(ll_temp) == np.ndarray, "init_st should be of type list"
    if q_init != None:
        assert type(q_init) == float, "init_st should be of type list"

    # input dimensions
    [rows, cols] = Raster.ReadAsArray().shape
    assert np.shape(sp_prec)[0] == rows and np.shape(
        sp_et)[0] == rows and np.shape(sp_temp)[0] == rows and np.shape(
            sp_pars
        )[0] == rows, "all input data should have the same number of rows"
    assert np.shape(sp_prec)[1] == cols and np.shape(
        sp_et)[1] == cols and np.shape(sp_temp)[1] == cols and np.shape(
            sp_pars
        )[1] == cols, "all input data should have the same number of columns"
    assert np.shape(sp_prec)[2] == np.shape(sp_et)[2] and np.shape(
        sp_temp)[2] == np.shape(sp_prec)[
            2], "all meteorological input data should have the same length"

    n_steps = sp_prec.shape[2] + 1  # no of time steps =length of time series +1
    # intiialise vector of nans to fill states
    dummy_states = np.empty([n_steps, 5])  # [sp,sm,uz,lz,wc]
    dummy_states[:] = np.nan
    dummy_states = np.float32(dummy_states)

    # Get the mask
    no_val = np.float32(Raster.GetRasterBand(1).GetNoDataValue())
    raster = Raster.ReadAsArray()

    # calculate area covered by cells
    geo_trans = Raster.GetGeoTransform(
    )  # get the coordinates of the top left corner and cell size [x,dx,y,dy]
    dx = np.abs(geo_trans[1]) / 1000.0  # dx in Km
    dy = np.abs(geo_trans[-1]) / 1000.0  # dy in Km
    px_area = dx * dy  # area of the cell
    no_cells = np.size(raster[:, :]) - np.count_nonzero(
        raster[raster == no_val])
    px_tot_area = no_cells * px_area  # total area of pixels

    st = []  # Spatially distributed states
    q_lz = []
    q_uz = []

    for x in range(rows):  # no of rows
        st_row = []
        q_lz_row = []
        q_uz_row = []

        for y in range(cols):  # no of columns
            if raster[x, y] != no_val:  # only for cells in the domain
                # Calculate the states per cell
                try:
                    uzg, lzg, stvar = ConceptualModel.Simulate(
                        prec=sp_prec[x, y, :],
                        temp=sp_temp[x, y, :],
                        et=sp_et[x, y, :],
                        par=sp_pars[x, y, :],
                        p2=p2,
                        init_st=init_st,
                        ll_temp=None,
                        q_init=q_init,
                        snow=0)
                except:
                    print("conceptual model argument are not correct")

                # append column after column in the same row


#                st_i.append(np.array(_st))
                st_row.append(stvar)

                # calculate upper zone Q = k*(UZ_int_3)**(1+alpha)
                #                q_uz_temp = np.array(sp_pars[x, y, 5])*(np.power(_uzg, (1.0 + sp_pars[x, y, 7])))
                #                q_uzi.append(q_uz_temp)
                q_uz_row.append(uzg)

                #calculate lower zone Q = K1*(LZ_int_1)
                #                q_lz_temp=np.array(sp_pars[x, y, 6])*_lzg
                #                q_lzi.append(q_lz_temp)
                q_lz_row.append(lzg)

    #                print("total = "+str(fff)+"/"+str(tot_elem)+" cell, row= "+str(x+1)+" column= "+str(y+1) )

            else:  # if the cell is novalue-------------------------------------
                # Fill the empty cells with a nan vector
                st_row.append(
                    dummy_states
                )  # fill all states(5 states) for all time steps = nan
                q_lz_row.append(
                    dummy_states[:, 0]
                )  # q lower zone =nan  for all time steps = nan
                q_uz_row.append(
                    dummy_states[:, 0]
                )  # q upper zone =nan  for all time steps = nan

    # store row by row-------- ----------------------------------------------------
    #        st.append(st_i) # state variables
        st.append(st_row)  # state variables
        q_lz.append(q_lz_row)  # lower zone discharge mm/timestep
        q_uz.append(q_uz_row)  # upper zone routed discharge mm/timestep
    #------------------------------------------------------------------------------
    # convert to arrays
    st = np.array(st)
    q_lz = np.array(q_lz)
    q_uz = np.array(q_uz)
    # convert quz from mm/time step to m3/sec
    area_coef = p2[1] / px_tot_area
    q_uz = q_uz * px_area * area_coef / (p2[0] * 3.6)

    #    # convert QLZ to 1D time series
    #    q_lz = np.array([np.nanmean(q_lz[:,:,i]) for i in range(n_steps)]) # average of all cells (not routed mm/timestep)
    #    # convert Qlz to m3/sec
    #    q_lz = q_lz* p2[1]/ (p2[0]*3.6) # generation

    q_lz = q_lz * px_area * area_coef / (p2[0] * 3.6)

    # convert all to float32 to save storage
    q_lz = np.float32(q_lz)
    q_uz = np.float32(q_uz)
    st = np.float32(st)
    return st, q_lz, q_uz
Exemple #2
0
def NearestCell(Raster, StCoord):
    """
    ======================================================
       NearestCell(Raster,StCoord)
    ======================================================
    this function calculates the the indices (row, col) of nearest cell in a given 
    raster to a station 
    coordinate system of the raster has to be projected to be able to calculate
    the distance
    
    Inputs:
    ----------
        1-Raster:
            [gdal.dataset] raster to get the spatial information (coordinates of each cell)
        2-StCoord:
            [Dataframe] dataframe with two columns "x", "y" contains the coordinates
            of each station
    
    Output:
    ----------
        1-StCoord:the same input dataframe with two extra columns "cellx","celly"
    
    Examples:
        soil_type=gdal.Open("DEM.tif")
        coordinates=stations[['id','x','y']][:]
        coordinates.loc[:,["cell_row","cell_col"]]=NearestCell(Raster,StCoord)
    """
    # input data validation
    # data type
    assert type(
        Raster
    ) == gdal.Dataset, "raster should be read using gdal (gdal dataset please read it using gdal library) "
    assert type(
        StCoord
    ) == pd.core.frame.DataFrame, "please check StCoord input it should be pandas dataframe "

    # check if the user has stored the coordinates in the dataframe with the right names or not
    assert "x" in StCoord.columns, "please check the StCoord x coordinates of the stations should be stored in a column name 'x'"
    assert "y" in StCoord.columns, "please check the StCoord y coordinates of the stations should be stored in a column name 'y'"

    StCoord['cell_row'] = np.nan
    StCoord['cell_col'] = np.nan

    rows = Raster.RasterYSize
    cols = Raster.RasterXSize
    geo_trans = Raster.GetGeoTransform(
    )  # get the coordinates of the top left corner and cell size [x,dx,y,dy]
    # X_coordinate= upperleft corner x+ index* cell size+celsize/2
    coox = np.ones((rows, cols))
    cooy = np.ones((rows, cols))
    for i in range(rows):  # iteration by row
        for j in range(cols):  # iteration by column
            coox[i, j] = geo_trans[0] + geo_trans[1] / 2 + j * geo_trans[
                1]  # calculate x
            cooy[i, j] = geo_trans[3] + geo_trans[5] / 2 + i * geo_trans[
                5]  # calculate y

    Dist = np.ones((rows, cols))
    for no in range(len(StCoord['x'])):
        # calculate the distance from the station to all cells
        for i in range(rows):  # iteration by row
            for j in range(cols):  # iteration by column
                Dist[i, j] = np.sqrt(
                    np.power((StCoord.loc[StCoord.index[no], 'x'] -
                              coox[i, j]), 2) +
                    np.power((StCoord.loc[StCoord.index[no], 'y'] -
                              cooy[i, j]), 2))

        StCoord.loc[no, 'cell_row'], StCoord.loc[no, 'cell_col'] = np.where(
            Dist == np.min(Dist))

    return StCoord.loc[:, ["cell_row", "cell_col"]]