Exemplo n.º 1
0
def getdir(rec, dirtif):

    dat = gdalutils.get_data(dirtif)
    geo = gdalutils.get_geo(dirtif)
    dirdf = gdalutils.array_to_pandas(dat, geo, 0, 'gt')
    recdf = gdalutils.assign_val(df2=rec.reset_index(),
                                 df2_x='lon',
                                 df2_y='lat',
                                 df1=dirdf,
                                 df1_x='x',
                                 df1_y='y',
                                 label='z',
                                 copy=True)

    # Direction of outlet is given by the maximum repetitions of directions in the last 10 points
    _dir = recdf.sort_values(
        by='distance').iloc[0:10].groupby('z')['z'].count().idxmax()

    return _dir
Exemplo n.º 2
0
    #########################################################################################
    # Get geometry information from acctif, assume all arrays have the same geometry
    #
    geo = gdalutils.get_geo(acctif)
    print(geo)
    # modify number of cells: divide by nwindow and round up (block_reduce pads the arrays)
    geo[4] = int(np.ceil(geo[4] / nwindow))
    geo[5] = int(np.ceil(geo[5] / nwindow))
    # modify resolution: multiply by nwindow
    geo[6] = geo[6] * nwindow
    geo[7] = geo[7] * nwindow

    #########################################################################################
    # Downsample dem array
    if not os.path.exists(dem_downsample):
        data = gdalutils.get_data(demtif)
        print('inshape', data.shape)
        downsample_dem = block_reduce(data,
                                      block_size=(nwindow, nwindow),
                                      func=np.mean,
                                      cval=-9999)
        print('downsampled dem', downsample_dem.shape)
        gdalutils.write_raster(downsample_dem, dem_downsample, geo, 'Float32',
                               -9999)

    #########################################################################################
    # Downsample ord and acc arrays (for calculation of directions)
    #
    if not os.path.exists(ord_downsample) or not os.path.exists(
            acc_downsample):
        data = gdalutils.get_data(ordtif)
Exemplo n.º 3
0
Arquivo: core.py Projeto: jsosa/banks
def calc_banks(banktif, bedtif, fname_disch, fname_stage, reccsv, return_per, layer, outfolder):

    # Loading stage and discharge files
    # Try statement added since some discharge and stage files are empty, exit program
    try:
        stage = lfp.read_stage(fname_stage)
        df_locs = lfp.read_stage_locs(fname_stage)
        df_locs.index = range(len(stage.columns))
        discharge = lfp.read_discharge(fname_disch)
        stage.columns = range(len(discharge.columns))
        discharge.columns = range(len(stage.columns))
    except ValueError:
        sys.exit('ERROR: Probably stage or discharge file is empty')

    # Loading Return Perid database (eg. FLOPROS)
    gdf_defenses = gpd.read_file(return_per)

    # Getting protection level from Return Period dataset at every cell
    # River points have been buffered to allow disaggrement between geolocations
    # By buffering some points get more than one value, maximum flood protection is selected
    mygeom = [Point(x, y) for x, y in zip(df_locs['x'], df_locs['y'])]
    gdf_locs = gpd.GeoDataFrame(crs={'init': 'epsg:4326'}, geometry=mygeom)
    gdf_locs_buf = gpd.GeoDataFrame(
        crs={'init': 'epsg:4326'}, geometry=gdf_locs.buffer(0.1))
    gdf_locs_ret = gpd.sjoin(gdf_locs_buf, gdf_defenses, op='intersects')
    gdf_locs_ret['index'] = gdf_locs_ret.index
    gdf_locs_ret = gdf_locs_ret.sort_values(
        layer, ascending=False).drop_duplicates('index').sort_values('index')

    # Estimating error in discharge fitting
    dis_err = []
    for i in range(discharge.shape[1]):
        try:
            dis_err.append(get_discharge_error(discharge[i]))
        except (KeyError,np.core._internal.AxisError):
            dis_err.append(0)

    # Estimating a defenses-related discharge
    dis_df = []
    for i in range(discharge.shape[1]):
        ret_pe = gdf_locs_ret['MerL_Riv'][i]
        try:
            dis_df.append(get_discharge_returnperiod(discharge[i], ret_pe))
        except (KeyError,np.core._internal.AxisError):
            dis_df.append(np.nan)

    # Estimating error in stage fitting
    stg_err = []
    for i in range(discharge.shape[1]):
        try:
            stg_err.append(get_stage_error(discharge[i], stage[i]))
        except (RuntimeError, TypeError):
            stg_err.append(0)

    # Estimating a defenses-related stage
    stg_df = []
    for i in range(discharge.shape[1]):
        try:
            stg_df.append(get_stage_discharge(
                discharge[i], stage[i], dis_df[i]))
        except (RuntimeError, TypeError):
            stg_df.append(np.nan)

    # Preparing a summary with variables retrived
    df_locs['dis_df'] = dis_df
    df_locs['stg_df'] = stg_df
    df_locs['dis_err'] = dis_err
    df_locs['stg_err'] = stg_err

    # Read REC file
    rec = pd.read_csv(reccsv)

    # Convert dataframe to geodataframe, join with rec
    gdf_sum = gpd.GeoDataFrame(df_locs, crs={'init': 'epsg:4326'}, geometry=[
        Point(x, y) for x, y in zip(df_locs['x'], df_locs['y'])])
    gdf_rec = gpd.GeoDataFrame(rec, crs={'init': 'epsg:4326'}, geometry=[
        Point(x, y) for x, y in zip(rec['lon'], rec['lat'])])
    gdf_rec_buf = gpd.GeoDataFrame(
        rec, crs={'init': 'epsg:4326'}, geometry=gdf_rec.buffer(0.001))
    gdf_sum_rec = gpd.sjoin(gdf_sum, gdf_rec_buf,
                            how='inner', op='intersects')
    gdf_sum_rec.sort_values('index_right', inplace=True)

    # Save errors in a GeoJSON file
    try:
        gdf_sum_rec.to_file(outfolder + 'bnk_err.geojson', driver='GeoJSON')
    except:
        os.remove(outfolder + 'bnk_err.geojson')
        gdf_sum_rec.to_file(outfolder + 'bnk_err.geojson', driver='GeoJSON')

    # Score should greater than 0.85 for both Discharge and Stage to be accepted, otherwise NaN
    gdf_err = gdf_sum_rec['stg_df'].where(
        (gdf_sum_rec['dis_err'] > 0.85) & (gdf_sum_rec['stg_err'] > 0.85))

    # Fill with NaN stg_df not filling that condition
    gdf_sum_rec['stg_df'] = gdf_err

    # NaNs are filled repating last/first number per link
    gdf_sum_rec_fillna = gdf_sum_rec.groupby('link').fillna(
        method='bfill').fillna(method='ffill')
    gdf_sum_rec_fillna['link'] = gdf_sum_rec['link']

    # Read data and geo for bedtif
    bed = gu.get_data(bedtif)
    geo = gu.get_geo(bedtif)

    # Convert dataframes to arrays
    df_locs_stgdf = gdf_sum_rec_fillna[['x', 'y', 'stg_df']]
    df_locs_stgdf.columns = ['x', 'y', 'z']
    arr_stgdf = gu.pandas_to_array(df_locs_stgdf, geo, 0)

    # Sum bankfull stage and defenses-related stage to bed
    arr_bnkdf = (bed + arr_stgdf)

    # Write burned banks in ASC and TIF files
    gu.write_raster(arr_bnkdf, banktif, geo, 'Float64', 0)
Exemplo n.º 4
0
def split(argv):
    """
    Info:
    -----
    Split area per basins

    Check if basin area is larger than 100 Km2, if yes, it continues

    Check if number of pixels in river network is larger than 35, if yes, continues

    Clip tree and coord files

    To Clip .tif files, it checks outlet direction and increases 0.1 degrees from 
    boundaries but no in the outlet boundary since it will obstruct the outflow.

    There is a “connections” function which finds connections between links. 
    Basically, creates a NNN_rec.csv file containing all river coordinates, three 
    classifications: 1) classification per “link” (given by TAUDEM), 2) classification 
    per reach (coordinates belonging to longer link) and 3) classification per 
    downstream link (given by TAUDEM), other features were added like strahler number 
    (given by TAUDEM) and distance to outlet (given by TAUDEM).


    Dependencies:
    -------------
    TAUDEM : streamnet, gagewatershed
    GDAL : gdalwarp
    Pandas, Numpy, GDAL Python API, gdalutils, prepdata_utils


    Inputs:
    -------
    basnum : Basin number or the keyword “all” to process
    cattif : A GDAL raster file containing basin numbers (one number per basin)
    demtif : DEM in GDAL raster
    acctif : Accumulation GDAL raster
    nettif : River network GDAL raster
    wthtif : River width GDAL raster
    dirtif : Flow directions GDAL raster
    aretif : Area GDAL raster
    otltif : Outlets GDAL raster
    tretxt : Tree file from TAUDEM
    cootxt : Coord file from TAUDEM
    outdir : Out path


    Outputs (If running at 30s):
    ----------------------------
    NNN_acc.tif
    NNN_coo.csv
    NNN_dem.tif
    NNN_dir.tif
    NNN_net.tif
    NNN_rec.csv
    NNN_tre.csv
    NNN_wth.tif
    """

    opts, args = getopt.getopt(argv, "i:")
    for o, a in opts:
        if o == "-i":
            inifile = a
    config = configparser.SafeConfigParser()
    config.read(inifile)

    basnum = str(config.get('split', 'basnum'))
    cattif = str(config.get('split', 'cattif'))
    demtif = str(config.get('split', 'demtif'))
    acctif = str(config.get('split', 'acctif'))
    nettif = str(config.get('split', 'nettif'))
    wthtif = str(config.get('split', 'wthtif'))
    dirtif = str(config.get('split', 'dirtif'))
    otltif = str(config.get('split', 'otltif'))
    aretif = str(config.get('split', 'aretif'))
    tretxt = str(config.get('split', 'tretxt'))
    cootxt = str(config.get('split', 'cootxt'))
    outdir = str(config.get('split', 'outdir'))

    print("    running split.py...")

    # Clip input maps per catchment
    if basnum == "all":
        # Loading data
        catarr = gdalutils.get_data(cattif)

        # Loop over all catchment numbers
        # Catchments should be numbered and > 0
        for nc in np.unique(catarr[catarr > 0]):
            basinsplit(nc, outdir, cattif, demtif, acctif, nettif,
                       wthtif, dirtif, aretif, otltif, tretxt, cootxt)
    else:
        # Process a single catchments
        b = basnum.split(',')
        for nc in b:
            print('processing basin number: ' + nc)
            basinsplit(int(nc), outdir, cattif, demtif, acctif, nettif,
                       wthtif, dirtif, aretif, otltif, tretxt, cootxt)
Exemplo n.º 5
0
def basinsplit(ncatch, outdir, cattif, demtif, acctif, nettif, wthtif, dirtif, aretif, otltif, tretxt, cootxt):

    # Get extend for every catchment and area
    catarr = gdalutils.get_data(cattif)

    try:
        dat = catarr == ncatch
    except:
        sys.exit('ERROR invalid basin number')

    catgeo = gdalutils.get_geo(cattif)
    area = gdalutils.get_data(aretif)
    outlet = gdalutils.get_data(otltif)
    direc = gdalutils.get_data(dirtif)
    row, col = np.where(dat)
    _sum = np.sum(dat*area)

    if _sum >= 100:  # be sure basin is larger than 100 Km2

        xmin = catgeo[8][min(col)]
        xmax = catgeo[8][max(col)]
        ymin = catgeo[9][max(row)]
        ymax = catgeo[9][min(row)]

        # Clip input rasters
        netarr_tmp, netgeo_tmp = gdalutils.clip_raster(
            nettif, xmin, ymin, xmax, ymax)
        catarr_tmp, catgeo_tmp = gdalutils.clip_raster(
            cattif, xmin, ymin, xmax, ymax)

        # Mask only the catchment and fill with zeros
        netarr_tmp = np.where(catarr_tmp == ncatch, netarr_tmp, 0)

        if netarr_tmp.sum() >= 35:  # be sure river network is long enough

            # Clipping tree and coord files based on nettif > 0, coordinates
            tree = misc_utils.read_tree_taudem(tretxt)
            coor = misc_utils.read_coord_taudem(cootxt)
            iy, ix = np.where(netarr_tmp > 0)
            Xrav = netgeo_tmp[8][ix]
            Yrav = netgeo_tmp[9][iy]

            # Clipping coord file (it may be improved, calculation takes some time)
            lfp_coor = pd.DataFrame()
            for i in range(len(Xrav)):
                dis, ind = misc_utils.near_euc(
                    coor['lon'].values, coor['lat'].values, (Xrav[i], Yrav[i]))
                if dis <= 0.01:
                    lfp_coor = lfp_coor.append(coor.loc[ind, :])
            lfp_coor = lfp_coor[['lon', 'lat',
                                 'distance', 'elev', 'contr_area']]
            lfp_coor.index.name = 'index'
            lfp_coor.sort_index(inplace=True)
            # Remove duplicates just in case
            lfp_coor.drop_duplicates(inplace=True)

            # Clipping tree file
            lfp_tree = pd.DataFrame()
            for i in tree.index:
                sta = tree.loc[i, 'start_pnt']
                end = tree.loc[i, 'end_pnt']
                lon1 = coor.loc[sta, 'lon']
                lat1 = coor.loc[sta, 'lat']
                lon2 = coor.loc[end, 'lon']
                lat2 = coor.loc[end, 'lat']
                dis1, ind1 = misc_utils.near_euc(
                    lfp_coor['lon'].values, lfp_coor['lat'].values, (lon1, lat1))
                dis2, ind2 = misc_utils.near_euc(
                    lfp_coor['lon'].values, lfp_coor['lat'].values, (lon2, lat2))
                # default value 0.01 wasn't able to find link number 3504, this value was increased to 0.012 to find missing link
                if (dis1 <= 0.012) & (dis2 <= 0.012):
                    lfp_tree = lfp_tree.append(tree.loc[i, :])
            lfp_tree = lfp_tree[['link_no', 'start_pnt', 'end_pnt', 'frst_ds',
                                 'frst_us', 'scnd_us', 'strahler', 'mon_pnt', 'shreve']]
            lfp_tree.index.name = 'index'

            # Creating folder per basin
            ncatchstr = "%03d" % ncatch
            folder = outdir + "/" + ncatchstr
            create_out_folder(folder)

            # Writing clipped coord and tree files
            fnametre = folder + "/" + ncatchstr + "_tre.csv"
            fnamecoo = folder + "/" + ncatchstr + "_coo.csv"
            lfp_coor.to_csv(fnamecoo)
            lfp_tree.to_csv(fnametre, float_format='%i')

            # Creating rec dataframe
            rec = connections(fnametre, fnamecoo)

            #  Writing XXX_rec.csv file
            fnamerec = folder + "/" + ncatchstr + "_rec.csv"
            rec.to_csv(fnamerec)

            # Get extent from rec dataframe
            xmin = rec['lon'].min()
            xmax = rec['lon'].max()
            ymin = rec['lat'].min()
            ymax = rec['lat'].max()

            # Get fixed extent
            # _dir    = getdir(rec,dirtif)
            # _dirlet = getdirletter(_dir)
            # xmin,ymin,xmax,ymax = get_extent_outlet(_dirlet,0.1,xmin,ymin,xmax,ymax)

            # Clipping rasters
            demarrcli, demgeocli = gdalutils.clip_raster(
                demtif, xmin, ymin, xmax, ymax)
            accarrcli, accgeocli = gdalutils.clip_raster(
                acctif, xmin, ymin, xmax, ymax)
            wtharrcli, wthgeocli = gdalutils.clip_raster(
                wthtif, xmin, ymin, xmax, ymax)
            dirarrcli, dirgeocli = gdalutils.clip_raster(
                dirtif, xmin, ymin, xmax, ymax)
            netarrcli, netgeocli = gdalutils.clip_raster(
                nettif, xmin, ymin, xmax, ymax)
            catarrcli, catgeocli = gdalutils.clip_raster(
                cattif, xmin, ymin, xmax, ymax)

            # Mask only the catchment and fill with zeros
            netarrcli = np.where(catarrcli == ncatch, netarrcli, 0)
            dirarrcli = np.where(catarrcli == ncatch, dirarrcli, 0)

            # Creating output names
            fnamedem = folder + "/" + ncatchstr + "_dem.tif"
            fnameacc = folder + "/" + ncatchstr + "_acc.tif"
            fnamenet = folder + "/" + ncatchstr + "_net.tif"
            fnamewth = folder + "/" + ncatchstr + "_wth.tif"
            fnamedir = folder + "/" + ncatchstr + "_dir.tif"

            # Writing clipped arrays
            nodata = -9999
            gdalutils.write_raster(demarrcli, fnamedem,
                                   demgeocli, "Float32", nodata)
            gdalutils.write_raster(accarrcli, fnameacc,
                                   accgeocli, "Float32", nodata)
            gdalutils.write_raster(netarrcli, fnamenet,
                                   netgeocli, "Float32", nodata)
            gdalutils.write_raster(wtharrcli, fnamewth,
                                   wthgeocli, "Float32", nodata)
            gdalutils.write_raster(dirarrcli, fnamedir,
                                   dirgeocli, "Float32", nodata)

        else:
            print("NOT PROCESSED: Number of pixels in river lower than 35 : " +
                  str(netarr_tmp.sum()) + " pixels in basin number " + str(ncatch))
    else:
        print("NOT PROCESSED: Basin area lower than 100 Km2 : " +
              str(_sum) + " KM**2 in basin number " + str(ncatch))
Exemplo n.º 6
0
def getbankelevs(output, netf, hrdemf, proj, method, hrnodata, thresh,
                 outlier):

    print("    running getbankelevs.py...")

    fname = output

    w = shapefile.Writer(shapefile.POINT)
    w.field('x')
    w.field('y')
    w.field('elev')

    # coordinates for bank elevations are based in river network mask
    net = gdalutils.get_data(netf)
    geo = gdalutils.get_geo(netf)
    iy, ix = np.where(net > 0)
    x = geo[8][ix]
    y = geo[9][iy]

    for i in range(len(x)):

        xmin = x[i] - thresh
        ymin = y[i] - thresh
        xmax = x[i] + thresh
        ymax = y[i] + thresh

        dem, dem_geo = gdalutils.clip_raster(hrdemf, xmin, ymin, xmax, ymax)
        ddem = np.ma.masked_where(dem == hrnodata, dem)

        if method == 'near':
            nodata = dem_geo[11]
            dfdem = gdalutils.array_to_pandas(dem, dem_geo, nodata, 'gt')
            arr = haversine.haversine_array(
                np.array(dfdem['y'].values, dtype='float32'),
                np.float32(dfdem['x'].values), np.float32(y[i]),
                np.float32(x[i]))
            dfdem['dis'] = np.array(arr)
            dfdem.sort_values(by='dis', inplace=True)
            elev = dfdem.iloc[0, 2]

        elif method == 'meanmin':
            if outlier == "yes":
                ddem = check_outlier(dem, ddem, hrnodata, 3.5)
            elev = np.mean([ddem.mean(), ddem.min()])

        elif method == 'mean':
            if outlier == "yes":
                ddem = check_outlier(dem, ddem, hrnodata, 3.5)
            elev = ddem.mean()

        elif method == 'min':
            if outlier == "yes":
                ddem = check_outlier(dem, ddem, hrnodata, 3.5)
            elev = ddem.min()

        # Write final file in a shapefile

        if np.isfinite(elev):
            w.point(x[i], y[i])
            w.record(x[i], y[i], elev)

    w.save("%s.shp" % fname)

    # Write .prj file
    prj = open("%s.prj" % fname, "w")
    srs = osr.SpatialReference()
    srs.ImportFromProj4(proj)
    prj.write(srs.ExportToWkt())
    prj.close()

    fmt = "GTiff"
    nodata = -9999
    bnkname1 = output + ".shp"
    bnkname2 = output + ".tif"
    subprocess.call([
        "gdal_rasterize", "-a_nodata",
        str(nodata), "-of", fmt, "-tr",
        str(geo[6]),
        str(geo[7]), "-a", "elev", "-a_srs", proj, "-te",
        str(geo[0]),
        str(geo[1]),
        str(geo[2]),
        str(geo[3]), bnkname1, bnkname2
    ])
    print(geo)

    if nwindow is not None:
        #########################################################################################

        # modify number of cells: divide by nwindow and round up (block_reduce pads the arrays)
        geo[4] = int(np.ceil(geo[4] / nwindow))
        geo[5] = int(np.ceil(geo[5] / nwindow))
        # modify resolution: multiply by nwindow
        geo[6] = geo[6] * nwindow
        geo[7] = geo[7] * nwindow

        #########################################################################################
        # Downsample chanmask arrays
        if not os.path.exists(maskraw_downsample):
            data = gdalutils.get_data(maskrawtif)
            downsample_count = block_reduce(data,
                                            block_size=(nwindow, nwindow),
                                            func=count,
                                            cval=-32767)
            data_mask = downsample_count >= count_thresh
            print('downsampled mask', data_mask.shape)
            gdalutils.write_raster(data_mask, maskraw_downsample, geo, 'Int16',
                                   -9999)
        else:
            data_mask = gdalutils.get_data(maskraw_downsample)
        #########################################################################################
        # Clean chanmask - remove values away from stream network
        data_net = gdalutils.get_data(net_downsample)
        data_maskclean = clean_mask(data_mask, data_net, 900)
        gdalutils.write_raster(data_maskclean, maskclean_downsample, geo,
Exemplo n.º 8
0
Arquivo: core.py Projeto: jsosa/beds
def beds(widthtif, bnkfixtif, runoffcsv, date1, date2, bedtif, lisfloodfp):

    # Create a temp temporal work folder
    outfolder = os.path.dirname(bedtif) + '/beds-temp/'
    try:
        os.makedirs(outfolder + 'lfp/nc/')
    except FileExistsError:
        pass

    # Determine end of the simulation, how many days
    t = (pd.to_datetime(date2, format='%Y-%m-%d') -
         pd.to_datetime(date1, format='%Y-%m-%d')).days + 1

    # Create 1D DEM, synthetic
    demtif = outfolder + 'dem1d.tif'
    wdt = gu.get_data(widthtif)
    geo = gu.get_geo(widthtif)
    dem = np.where(wdt > 0, 10000, 0)
    gu.write_raster(dem, demtif, geo, 'Int16', 0)

    # Convert input files to ASCII
    widthasc = outfolder + 'width.asc'
    call(['gdal_translate',
          '-of', 'AAIGRID',
          widthtif, widthasc])

    demasc = outfolder + 'dem.asc'
    call(['gdal_translate',
          '-of', 'AAIGRID',
          demtif, demasc])

    bnkfixasc = outfolder + 'bnkfix.asc'
    call(['gdal_translate',
          '-of', 'AAIGRID',
          bnkfixtif, bnkfixasc])

    # Write LISFLOOD-FP files
    bcilfp = outfolder + 'lfp.bci'
    write_bci(bcilfp, runoffcsv)

    bdylfp = outfolder + 'lfp.bdy'
    write_bdy(bdylfp, runoffcsv, t)

    evaplfp = outfolder + 'lfp.evap'
    write_evap(evaplfp, t)

    parlfp = outfolder + 'lfp.par'
    write_par(parlfp=parlfp,
              bcilfp=bcilfp,
              bdylfp=bdylfp,
              evaplfp=evaplfp,
              gaugelfp='./none',
              stagelfp='./none',
              dembnktif=demasc,
              wdttif=widthasc,
              bedtif=bnkfixasc,
              t=t)

    # Run simulation
    call([lisfloodfp, '-v', 'lfp.par'], cwd=outfolder)

    # Write netCDFs for WATER DEPTHS
    myfiles = sorted(glob(outfolder + '/lfp/*.wd'))
    for myfile in myfiles:
        fname = outfolder + 'lfp/nc/' + os.path.basename(myfile) + '.nc'
        xr.open_rasterio(myfile).to_dataset(name='myvar').to_netcdf(fname)

    # Read netCDFs
    ds = xr.open_mfdataset(outfolder + 'lfp/nc/*.nc',
                           concat_dim='band',
                           autoclose=True,
                           parallel=False,
                           chunks={'band': 10})

    # Calculating mean
    method = ds.where(ds > 0, 0).myvar.mean('band')

    # Saving result in netCDF
    method.to_netcdf(outfolder + 'mean.nc')

    # Reading banks
    bnkfix = gu.get_data(bnkfixtif)
    bnkfix = np.where(bnkfix > 0, bnkfix, 0)

    # Calculating bed
    bed = bnkfix - method.compute().data

    # Write final raster
    gu.write_raster(bed, bedtif, geo, 'Float64', 0)
Exemplo n.º 9
0
def basinsplit(ncatch, outdir, cattif, demtif, acctif, nettif, wthtif, dirtif,
               aretif, ordtif, tretxt, cootxt):

    # Get extend for every catchment and area
    catarr = gdalutils.get_data(cattif)

    try:
        dat = catarr == ncatch
    except:
        sys.exit('ERROR invalid basin number')

    # Use gdal to mask out basin in network and direction tifs
    nettmp = 'net_tmp.tif'
    dirtmp = 'dir_tmp.tif'
    acctmp = 'acc_tmp.tif'
    ordtmp = 'ord_tmp.tif'
    cmd = [
        'gdal_calc.py', '--calc', 'where(B==' + str(ncatch) + ',A,0)',
        '--format', 'GTiff', '--type', 'Int16', '--NoDataValue', '-9999', '-B',
        cattif, '--B_band', '1', '-A', nettif, '--A_band', '1', '--co',
        'COMPRESS=DEFLATE', '--outfile', nettmp
    ]
    subprocess.call(cmd)
    cmd = [
        'gdal_calc.py', '--calc', 'where(B==' + str(ncatch) + ',A,0)',
        '--format', 'GTiff', '--type', 'Int16', '--NoDataValue', '-9999', '-B',
        cattif, '--B_band', '1', '-A', dirtif, '--A_band', '1', '--co',
        'COMPRESS=DEFLATE', '--outfile', dirtmp
    ]
    subprocess.call(cmd)
    cmd = [
        'gdal_calc.py', '--calc', 'where(B==' + str(ncatch) + ',A,0)',
        '--format', 'GTiff', '--type', 'Float32', '--NoDataValue', '-9999',
        '-B', cattif, '--B_band', '1', '-A', acctif, '--A_band', '1', '--co',
        'COMPRESS=DEFLATE', '--outfile', acctmp
    ]
    subprocess.call(cmd)
    cmd = [
        'gdal_calc.py', '--calc', 'where(B==' + str(ncatch) + ',A,0)',
        '--format', 'GTiff', '--type', 'Int16', '--NoDataValue', '-9999', '-B',
        cattif, '--B_band', '1', '-A', ordtif, '--A_band', '1', '--co',
        'COMPRESS=DEFLATE', '--outfile', ordtmp
    ]
    subprocess.call(cmd)
    print('separated basin for nettif, dirtif, acctif, ordtif')

    catgeo = gdalutils.get_geo(cattif)
    area = gdalutils.get_data(aretif)
    #outlet = gdalutils.get_data(otltif)
    #direc = gdalutils.get_data(dirtif)
    row, col = np.where(dat)
    _sum = np.sum(dat * area)
    # clean up
    del (catarr, dat, area)

    if _sum >= 100:  # be sure basin is larger than 100 Km2

        xmin = catgeo[8][min(col)]
        xmax = catgeo[8][max(col)]
        ymin = catgeo[9][max(row)]
        ymax = catgeo[9][min(row)]
        # Clean up
        del (row, col)

        # Clip input rasters
        netarr_tmp, netgeo_tmp = gdalutils.clip_raster(nettmp, xmin, ymin,
                                                       xmax, ymax)
        net_size = (netarr_tmp > 0).sum()
        print('loaded net array')

        if net_size >= 35:  # be sure river network is long enough

            # Load tree and coord files
            tree = misc_utils.read_tree_taudem(tretxt)
            lfp_coor = misc_utils.read_coord_taudem(cootxt)
            lfp_coor.index.name = 'index'

            # Get list of x,y points in river network in basin
            iy, ix = np.where(netarr_tmp > 0)
            Xrav = netgeo_tmp[8][ix]
            Yrav = netgeo_tmp[9][iy]
            # Clean up memory
            del (netarr_tmp)

            # Clipping tree file based on segments within basin
            print('Clipping tree file')
            lfp_tree = pd.DataFrame()
            for i in tree.index:
                sta = tree.loc[i, 'start_pnt']
                end = tree.loc[i, 'end_pnt']
                lon1 = lfp_coor.loc[sta, 'lon']
                lat1 = lfp_coor.loc[sta, 'lat']
                lon2 = lfp_coor.loc[end, 'lon']
                lat2 = lfp_coor.loc[end, 'lat']
                #                dis1, ind1 = misc_utils.near_euc(
                #                    lfp_coor['lon'].values, lfp_coor['lat'].values, (lon1, lat1))
                #                dis2, ind2 = misc_utils.near_euc(
                #                    lfp_coor['lon'].values, lfp_coor['lat'].values, (lon2, lat2))
                dis1, ind1 = misc_utils.near_euc(Xrav, Yrav, (lon1, lat1))
                dis2, ind2 = misc_utils.near_euc(Xrav, Yrav, (lon2, lat2))
                # default value 0.01 wasn't able to find link number 3504, this value was increased to 0.012 to find missing link
                if (dis1 <= 0.012) & (dis2 <= 0.012):
                    lfp_tree = lfp_tree.append(tree.loc[i, :])
            lfp_tree = lfp_tree[[
                'link_no', 'start_pnt', 'end_pnt', 'frst_ds', 'frst_us',
                'scnd_us', 'strahler', 'mon_pnt', 'shreve'
            ]]
            lfp_tree.index.name = 'index'

            # Creating folder per basin
            ncatchstr = "%03d" % ncatch
            folder = outdir + "/" + ncatchstr
            create_out_folder(folder)

            # Writing clipped coord and tree files
            print('Writing text files')
            fnametre = folder + "/" + ncatchstr + "_tre.csv"
            fnamecoo = folder + "/" + ncatchstr + "_coo.csv"
            lfp_coor.to_csv(fnamecoo)
            lfp_tree.to_csv(fnametre, float_format='%i')
            # clean up memory
            del (lfp_coor, lfp_tree)

            # Creating rec dataframe
            rec = connections(fnametre, fnamecoo)

            #  Writing XXX_rec.csv file
            fnamerec = folder + "/" + ncatchstr + "_rec.csv"
            rec.to_csv(fnamerec)

            # Get extent from rec dataframe
            xmin = rec['lon'].min()
            xmax = rec['lon'].max()
            ymin = rec['lat'].min()
            ymax = rec['lat'].max()
            # Clean up memory
            del (rec)

            # Get fixed extent
            # _dir    = getdir(rec,dirtif)
            # _dirlet = getdirletter(_dir)
            # xmin,ymin,xmax,ymax = get_extent_outlet(_dirlet,0.1,xmin,ymin,xmax,ymax)

            # Clipping rasters
            print('Loading and clipping rasters')
            nodata = -9999
            # Creating output names
            fnamedem = folder + "/" + ncatchstr + "_dem.tif"
            fnameacc = folder + "/" + ncatchstr + "_acc.tif"
            fnamenet = folder + "/" + ncatchstr + "_net.tif"
            fnamewth = folder + "/" + ncatchstr + "_wth.tif"
            fnamedir = folder + "/" + ncatchstr + "_dir.tif"
            fnameord = folder + "/" + ncatchstr + "_ord.tif"

            # Load and write each array before removing it from memory
            demarrcli, demgeocli = gdalutils.clip_raster(
                demtif, xmin, ymin, xmax, ymax)
            gdalutils.write_raster(demarrcli, fnamedem, demgeocli, "Float32",
                                   nodata)
            del (demarrcli, demgeocli)

            accarrcli, accgeocli = gdalutils.clip_raster(
                acctmp, xmin, ymin, xmax, ymax)
            gdalutils.write_raster(accarrcli, fnameacc, accgeocli, "Float32",
                                   nodata)
            del (accarrcli, accgeocli)

            wtharrcli, wthgeocli = gdalutils.clip_raster(
                wthtif, xmin, ymin, xmax, ymax)
            gdalutils.write_raster(wtharrcli, fnamewth, wthgeocli, "Float32",
                                   nodata)
            del (wtharrcli, wthgeocli)

            dirarrcli, dirgeocli = gdalutils.clip_raster(
                dirtmp, xmin, ymin, xmax, ymax)
            gdalutils.write_raster(dirarrcli, fnamedir, dirgeocli, "Int16",
                                   nodata)
            del (dirarrcli, dirgeocli)

            netarrcli, netgeocli = gdalutils.clip_raster(
                nettmp, xmin, ymin, xmax, ymax)
            gdalutils.write_raster(netarrcli, fnamenet, netgeocli, "Int16",
                                   nodata)
            del (netarrcli, netgeocli)

            ordarrcli, ordgeocli = gdalutils.clip_raster(
                ordtmp, xmin, ymin, xmax, ymax)
            gdalutils.write_raster(ordarrcli, fnameord, ordgeocli, "Int16",
                                   nodata)
            del (ordarrcli, ordgeocli)

            # Finally delete the nettmp and dirtmp files
            os.remove(nettmp)
            os.remove(dirtmp)
            os.remove(ordtmp)
            os.remove(acctmp)

        else:
            print("NOT PROCESSED: Number of pixels in river lower than 35 : " +
                  str(net_size) + " pixels in basin number " + str(ncatch))
    else:
        print("NOT PROCESSED: Basin area lower than 100 Km2 : " + str(_sum) +
              " KM**2 in basin number " + str(ncatch))