Exemplo n.º 1
0
def repnd_by_rstval(ref_rst, val_rst, out_rst):
    """
    Replace NoData Values with values from another raster
    """

    import numpy as np
    from osgeo import gdal
    from glass.g.wt.rst import obj_to_rst

    # TODO check if shape of two rasters are the same

    # Open Rasters and Get data as array
    refsrc = gdal.Open(ref_rst, gdal.GA_ReadOnly)
    popsrc = gdal.Open(val_rst, gdal.GA_ReadOnly)

    nd_val = refsrc.GetRasterBand(1).GetNoDataValue()
    nd_pop = refsrc.GetRasterBand(1).GetNoDataValue()

    refnum = refsrc.GetRasterBand(1).ReadAsArray()
    popnum = popsrc.GetRasterBand(1).ReadAsArray()

    # Replace NoData Values
    np.copyto(refnum, popnum, where=refnum==nd_val)

    # Export to file
    obj_to_rst(refnum, out_rst, refsrc, noData=nd_pop)

    return out_rst
Exemplo n.º 2
0
Arquivo: rst.py Projeto: jasp382/glass
def bands_to_rst(inRst, outFolder):
    """
    Export all bands of a raster to a new dataset
    
    TODO: this could be done using gdal_translate
    """

    import numpy
    import os
    from osgeo import gdal
    from glass.g.wt.rst import obj_to_rst
    from glass.g.prop.rst import get_nodata

    rst = gdal.Open(inRst)

    if rst.RasterCount == 1:
        return

    nodata = get_nodata(inRst)

    for band in range(rst.RasterCount):
        band += 1
        src_band = rst.GetRasterBand(band)
        if src_band is None:
            continue
        else:
            # Convert to array
            array = numpy.array(src_band.ReadAsArray())
            obj_to_rst(array,
                       os.path.join(
                           outFolder, '{r}_{b}.tif'.format(r=os.path.basename(
                               os.path.splitext(inRst)[0]),
                                                           b=str(band))),
                       inRst,
                       noData=nodata)
Exemplo n.º 3
0
def gdal_mapcalc(expression, exp_val_paths, outRaster, template_rst,
    outNodata=-99999):
    """
    GDAL Raster Calculator
    
    TODO: Check if rasters dimensions are equal
    """
    
    import numpy            as np
    from osgeo              import gdal
    from py_expression_eval import Parser
    from glass.g.prop.img   import get_nd
    from glass.g.wt.rst     import obj_to_rst
    
    parser = Parser()
    
    EXPRESSION = parser.parse(expression)
    
    evalValue = {}
    noDatas   = {}
    for x in EXPRESSION.variables():
        img = gdal.Open(exp_val_paths[x])
        arr = img.ReadAsArray().astype(float)
        
        evalValue[x] = arr
        noDatas[x]   = get_nd(img)
    
    result = EXPRESSION.evaluate(evalValue)
    
    for v in noDatas:
        np.place(result, evalValue[v]==noDatas[v], outNodata)
    
    # Write output and return
    
    return obj_to_rst(result, outRaster, template_rst, noData=outNodata)
Exemplo n.º 4
0
def nbr(nir, swir, outrst):
    """
    Normalized Burn Ratio
    
    EXPRESSION Sentinel-2A: (9-12) / (9+12)
    """
    
    import numpy        as np
    from osgeo          import gdal, gdal_array
    from glass.g.wt.rst import obj_to_rst
    
    # Open Images
    srcNir  = gdal.Open(nir, gdal.GA_ReadOnly)
    srcSwir = gdal.Open(swir, gdal.GA_ReadOnly)
    
    # To Array
    numNir  = srcNir.GetRasterBand(1).ReadAsArray().astype(float)
    numSwir = srcSwir.GetRasterBand(1).ReadAsArray().astype(float)
    
    # Do Calculation
    nbr = (numNir - numSwir) / (numNir + numSwir)
    
    # Place NoData Value
    nirNdVal  = srcNir.GetRasterBand(1).GetNoDataValue()
    swirNdVal = srcSwir.GetRasterBand(1).GetNoDataValue()
    
    nd = np.amin(nbr) - 1
    
    np.place(nbr, numNir == nirNdVal, nd)
    np.place(nbr, numSwir == swirNdVal, nd)
    
    # Export Result
    return obj_to_rst(nbr, outrst, nir, noData=nd)
Exemplo n.º 5
0
def rst_mean(rsts, out_rst):
    """
    Return rasters mean
    """

    import numpy as np
    from osgeo import gdal
    from glass.g.wt.rst import obj_to_rst

    # Open images
    src_rst = [gdal.Open(i, gdal.GA_ReadOnly) for i in rsts]

    # To Array
    num_rst = [s.GetRasterBand(1).ReadAsArray() for s in src_rst]

    # Sum all rasters
    num_out = num_rst[0]
    for i in range(1, len(num_rst)):
        num_out = num_out + num_rst[i]

    # Get Mean
    num_out = num_out / len(rsts)

    # Place NoDatas
    nd_out = np.amin(num_out) - 1
    for r in range(len(src_rst)):
        nd_val = src_rst[r].GetRasterBand(1).GetNoDataValue()

        np.place(num_out, num_rst[r] == nd_val, nd_out)

    # Export result
    return obj_to_rst(num_out, out_rst, src_rst[0], noData=nd_out)
Exemplo n.º 6
0
def resample_by_majority(refrst, valrst, out_rst):
    """
    Resample valrst based on refrst:
        Get Majority value of valrst for each cell in refrst

    Useful when ref raster has cellsize greater
    than value raster.

    TODO: Valrst must be of int type
    """

    import numpy          as np
    from osgeo            import gdal
    from glass.g.prop.img import get_cell_size, get_nd
    from glass.g.wt.rst   import obj_to_rst

    # Data to Array
    if type(refrst) == gdal.Dataset:
        refsrc = refrst
    
    else:
        refsrc = gdal.Open(refrst)
    
    if type(valrst) == gdal.Dataset:
        valsrc = valrst
    else:
        valsrc = gdal.Open(valrst)

    refnum = refsrc.ReadAsArray()
    valnum = valsrc.ReadAsArray()

    # Get Ref shape
    ref_shape = refnum.shape

    # in a row, how many cells valnum are for each refnum cell
    refcs = int(get_cell_size(refsrc)[0])
    valcs = int(get_cell_size(valsrc)[0])
    dcell = int(refcs / valcs)

    # Valnum must be of int type

    # Create generalized/resampled raster
    resnum = np.zeros(ref_shape, dtype=valnum.dtype)

    for row in range(ref_shape[0]):
        for col in range(ref_shape[1]):
            resnum[row, col] = np.bincount(
                valnum[row*dcell:row*dcell+dcell, col*dcell : col*dcell+dcell].reshape(dcell*dcell)
            ).argmax()
    
    # Export out raster
    return obj_to_rst(resnum, out_rst, refsrc, noData=get_nd(valsrc))
Exemplo n.º 7
0
Arquivo: rot.py Projeto: jasp382/glass
def rst_rotation(inFolder, template, outFolder, img_format='.tif'):
    """
    Invert raster data
    """

    import os
    from osgeo import gdal
    from glass.pys.oss import lst_ff
    from glass.g.rd.rst import rst_to_array
    from glass.g.prop.rst import get_nodata
    from glass.g.wt.rst import obj_to_rst

    rasters = lst_ff(inFolder, file_format=img_format)

    for rst in rasters:
        a = rst_to_array(rst)
        nd = get_nodata(rst)

        obj_to_rst(a[::-1],
                   os.path.join(outFolder, os.path.basename(rst)),
                   template,
                   noData=nd)

    return outFolder
Exemplo n.º 8
0
def rstval_to_binrst(rst, outfld, fileformat=None):
    """
    Export all values in a raster to new binary raster
    """

    import os
    import numpy as np
    from osgeo import gdal
    from glass.g.wt.rst import obj_to_rst
    from glass.pys.oss import fprop

    fileformat = fileformat if fileformat else '.tif'

    rst_src = gdal.Open(rst, gdal.GA_ReadOnly)

    # Get Nodata
    nd = rst_src.GetRasterBand(1).GetNoDataValue()

    # Data To Array
    rst_num = rst_src.GetRasterBand(1).ReadAsArray()

    # Get Unique values in Raster
    val = np.unique(rst_num)
    val = list(val[val != nd])

    fn = fprop(rst, 'fn')
    for v in val:
        # Create new binary array
        val_a = np.zeros(rst_num.shape, dtype=np.uint8)
        np.place(val_a, rst_num == v, 1)

        # Export to new raster
        obj_to_rst(val_a,
                   os.path.join(outfld, fn + '_val' + str(v) + fileformat),
                   rst_src,
                   noData=0)
Exemplo n.º 9
0
def ndvi(nir, red, outRst):
    """
    Apply Normalized Difference NIR/Red Normalized Difference
    Vegetation Index, Calibrated NDVI - CDVI
    
    https://www.indexdatabase.de/db/i-single.php?id=58
    
    EXPRESSION: (nir - red) / (nir + red)
    """
    
    import numpy        as np
    from osgeo          import gdal, gdal_array
    from glass.g.wt.rst import obj_to_rst
    
    # Open Images
    src_nir = gdal.Open(nir, gdal.GA_ReadOnly)
    src_red = gdal.Open(red, gdal.GA_ReadOnly)
    
    # To Array
    num_nir = src_nir.GetRasterBand(1).ReadAsArray().astype(float)
    num_red = src_red.GetRasterBand(1).ReadAsArray().astype(float)
    
    # Do Calculation
    ndvi = (num_nir - num_red) / (num_nir + num_red)
    
    # Place NoData Value
    nirNdVal = src_nir.GetRasterBand(1).GetNoDataValue()
    redNdVal = src_red.GetRasterBand(1).GetNoDataValue()
    
    ndNdvi = np.amin(ndvi) - 1
    
    np.place(ndvi, num_nir==nirNdVal, ndNdvi)
    np.place(ndvi, num_red==redNdVal, ndNdvi)
    
    # Export Result
    return obj_to_rst(ndvi, outRst, nir, noData=ndNdvi)
Exemplo n.º 10
0
Arquivo: rst.py Projeto: jasp382/glass
def rst_to_tiles(rst, n_tiles_x, n_tiles_y, out_folder):
    """
    Raster file to tiles
    """

    import os
    from glass.pys.oss import fprop
    from osgeo import gdal
    from glass.g.wt.rst import obj_to_rst

    rstprop = fprop(rst, ['fn', 'ff'])
    rstn, rstf = rstprop['filename'], rstprop['fileformat']

    # Open Raster
    img = gdal.Open(rst, gdal.GA_ReadOnly)

    # Get raster Geo Properties
    geotrans = img.GetGeoTransform()

    # Get rows and columns number of original raster
    nrows, ncols = img.RasterYSize, img.RasterXSize

    # Get rows and columns number for the tiles
    tile_rows = int(nrows / n_tiles_y)
    tile_cols = int(ncols / n_tiles_x)

    if tile_rows == nrows / n_tiles_y:
        remain_rows = 0
    else:
        remain_rows = nrows - (tile_rows * n_tiles_y)

    if tile_cols == ncols / n_tiles_x:
        remain_cols = 0
    else:
        remain_cols = ncols - (tile_cols * n_tiles_x)

    # Create news raster
    rst_num = img.GetRasterBand(1).ReadAsArray()
    nd = img.GetRasterBand(1).GetNoDataValue()

    for tr in range(n_tiles_y):
        if tr + 1 == n_tiles_y:
            __tile_rows = tile_rows + remain_rows
        else:
            __tile_rows = tile_rows

        top = geotrans[3] + (geotrans[5] * (tr * tile_rows))

        for tc in range(n_tiles_x):
            if tc + 1 == n_tiles_x:
                __tile_cols = tile_cols + remain_cols

            else:
                __tile_cols = tile_cols

            left = geotrans[0] + (geotrans[1] * (tc * tile_cols))

            nr = rst_num[tr * tile_rows:tr * tile_rows + __tile_rows,
                         tc * tile_cols:tc * tile_cols + __tile_cols]

            # New array to file
            obj_to_rst(nr,
                       os.path.join(
                           out_folder,
                           rstn + '_' + str(tr) + '_' + str(tc) + rstf),
                       img,
                       noData=nd,
                       geotrans=(left, geotrans[1], geotrans[2], top,
                                 geotrans[4], geotrans[5]))

    return out_folder
Exemplo n.º 11
0
Arquivo: cls.py Projeto: jasp382/glass
def k_means(imgFiles, out, n_cls=8):
    """
    K-Means implementation
    """

    import os
    from osgeo import gdal, gdal_array
    import numpy as np
    from sklearn import cluster
    from glass.g.wt.rst import obj_to_rst

    gdal.UseExceptions()
    gdal.AllRegister()

    singleBand = None
    if type(imgFiles) != list:
        # Check if img is a valid file
        if not os.path.exists(imgFiles):
            raise ValueError("{} is not a valid file".format(imgFiles))

        img_src = gdal.Open(imgFiles, gdal.GA_ReadOnly)

        n_bnd = img_src.RasterCount

        ndVal = img_src.GetRasterBand(1).GetNoDataValue()

        if n_bnd == 1:
            band = img_src.GetRasterBand(1)

            img = band.ReadAsArray()

            singleBand = 1
            #X = img.reshape((-1, 1))

        else:
            img = np.zeros((img_src.RasterYSize, img_src.RasterXSize, n_bnd),
                           gdal_array.GDALTypeCodeToNumericTypeCode(
                               img_src.GetRasterBand(1).DataType))

            for b in range(img.shape[2]):
                img[:, :, b] = img_src.GetRasterBand(b + 1).ReadAsArray()

    else:
        img_src = [gdal.Open(i, gdal.GA_ReadOnly) for i in imgFiles]

        ndVal = img_src[0].GetRasterBand(1).GetNoDataValue()

        n_bnd = len(img_src)

        img = np.zeros(
            (img_src[0].RasterYSize, img_src[0].RasterXSize, len(img_src)),
            gdal_array.GDALTypeCodeToNumericTypeCode(
                img_src[0].GetRasterBand(1).DataType))

        for b in range(img.shape[2]):
            img[:, :, b] = img_src[b].GetRasterBand(1).ReadAsArray()

    # Reshape arrays for classification
    if not singleBand:
        new_shape = (img.shape[0] * img.shape[1], img.shape[2])

        X = img[:, :, :n_bnd].reshape(new_shape)

    else:
        X = img.reshape((-1, 1))

    kmeans = cluster.KMeans(n_clusters=n_cls)

    kmeans.fit(X)

    X_cluster = kmeans.labels_

    if not singleBand:
        X_cluster = X_cluster.reshape(img[:, :, 0].shape)
    else:
        X_cluster = X_cluster.reshape(img.shape)

    # Place nodata values
    if type(imgFiles) != list:
        tmp = img_src.GetRasterBand(1).ReadAsArray()
    else:
        tmp = img_src[0].GetRasterBand(1).ReadAsArray()

    np.place(X_cluster, tmp == ndVal, 255)

    return obj_to_rst(X_cluster,
                      out,
                      imgFiles if type(imgFiles) != list else imgFiles[0],
                      noData=255)
Exemplo n.º 12
0
def update_globe_land_cover(original_globe_raster, osm_urban_atlas_raster,
                            osm_globe_raster, epsg, updated_globe_raster,
                            detailed_globe_raster):
    """
    Update the original Glob Land 30 with the result of the conversion of
    OSM DATA to the Globe Land Cover nomenclature;
    
    Also updates he previous updated Glob Land 30 with the result of the
    conversion of osm data to the Urban Atlas Nomenclature
    """

    import os
    import numpy as np
    from glass.g.rd.rst import rst_to_array
    from glass.g.prop.rst import get_cellsize, get_nodata
    from glass.g.wt.rst import obj_to_rst

    # ############################# #
    # Convert images to numpy array #
    # ############################# #
    np_globe_original = rst_to_array(original_globe_raster)
    np_globe_osm = rst_to_array(osm_globe_raster)
    np_ua_osm = rst_to_array(osm_urban_atlas_raster)

    # ################################## #
    # Check the dimension of both images #
    # ################################## #
    if np_globe_original.shape != np_globe_osm.shape:
        return (
            'The Globe Land 30 raster (original) do not have the same number'
            ' of columns/lines comparing with the Globe Land 30 derived '
            'from OSM data')

    elif np_globe_original.shape != np_ua_osm.shape:
        return (
            'The Globe Land 30 raster (original) do not have the same '
            'number of columns/lines comparing with the Urban Atlas raster '
            'derived from OSM data')

    elif np_globe_osm.shape != np_ua_osm.shape:
        return (
            'The Globe Land 30 derived from OSM data do not have the same '
            'number of columns/lines comparing with the Urban Atlas raster '
            'derived from OSM data')

    # ############## #
    # Check Cellsize #
    # ############## #
    cell_of_rsts = get_cellsize(
        [original_globe_raster, osm_globe_raster, osm_urban_atlas_raster],
        xy=True,
        gisApi='gdal')

    cell_globe_original = cell_of_rsts[original_globe_raster]
    cell_globe_osm = cell_of_rsts[osm_globe_raster]
    cell_ua_osm = cell_of_rsts[osm_urban_atlas_raster]

    if cell_globe_original != cell_globe_osm:
        return (
            'The cellsize of the Globe Land 30 raster (original) is not the '
            'same comparing with the Globe Land 30 derived from OSM data')

    elif cell_globe_original != cell_ua_osm:
        return (
            'The cellsize of the Globe Land 30 raster (original) is not the '
            'same comparing with the Urban Atlas raster derived from OSM data')

    elif cell_ua_osm != cell_globe_osm:
        return (
            'The cellsize of the Globe Land 30 derived from OSM data is not '
            'the same comparing with the Urban Atlas raster derived from '
            'OSM data')

    # ############################# #
    # Get the Value of Nodata Cells #
    # ############################# #
    nodata_glob_original = get_nodata(original_globe_raster, gisApi='gdal')
    nodata_glob_osm = get_nodata(osm_globe_raster, gisApi='gdal')
    nodata_ua_osm = get_nodata(osm_urban_atlas_raster, gisApi='gdal')

    # ######################################## #
    # Create a new map - Globe Land 30 Updated #
    # ######################################## #
    """
    Create a new array with zeros...
    
    1) The zeros will be replaced by the values in the Globe Land derived from
    OSM.
    
    2) The zeros will be replaced by the values in the Original Globe Land at
    the cells with NULL data in the Globe Land derived from OSM.
    
    The meta array will identify values origins in the updated raster:
    1 - Orinal Raster
    2 - OSM Derived Raster
    """

    update_array = np.zeros(
        (np_globe_original.shape[0], np_globe_original.shape[1]))

    update_meta_array = np.zeros(
        (np_globe_original.shape[0], np_globe_original.shape[1]))

    # 1)
    np.copyto(update_array, np_globe_osm, 'no',
              np_globe_osm != nodata_glob_osm)
    # 1) meta
    np.place(update_meta_array, update_array != 0, 2)
    # 2) meta
    np.place(update_meta_array, update_array == 0, 1)
    # 2)
    np.copyto(update_array, np_globe_original, 'no', update_array == 0)
    # 2) meta
    np.place(update_meta_array, update_array == nodata_glob_original,
             int(nodata_glob_original))
    # noData to int
    np.place(update_array, update_array == nodata_glob_original,
             int(nodata_glob_original))

    updated_meta = os.path.join(
        os.path.dirname(updated_globe_raster), '{n}_meta{e}'.format(
            n=os.path.splitext(os.path.basename(updated_globe_raster))[0],
            e=os.path.splitext(os.path.basename(updated_globe_raster))[1]))
    # Create Updated Globe Cover 30
    obj_to_rst(update_array,
               updated_globe_raster,
               original_globe_raster,
               noData=int(nodata_glob_original))
    # Create Updated Globe Cover 30 meta
    obj_to_rst(update_meta_array,
               updated_meta,
               original_globe_raster,
               noData=int(nodata_glob_original))

    # ################################################# #
    # Create a new map - Globe Land 30 Detailed with UA #
    # ################################################# #
    np_update = rst_to_array(updated_globe_raster)

    detailed_array = np.zeros((np_update.shape[0], np_update.shape[1]))

    detailed_meta_array = np.zeros((np_update.shape[0], np_update.shape[1]))
    """
    Replace 80 Globe Land for 11, 12, 13, 14 of Urban Atlas
    
    The meta array will identify values origins in the detailed raster:
    1 - Updated Raster
    2 - UA Derived Raster from OSM
    """
    # Globe - Mantain some classes
    np.place(detailed_array, np_update == 30, 8)
    np.place(detailed_array, np_update == 30, 1)

    np.place(detailed_array, np_update == 40, 9)
    np.place(detailed_array, np_update == 40, 1)

    np.place(detailed_array, np_update == 50, 10)
    np.place(detailed_array, np_update == 50, 1)

    np.place(detailed_array, np_update == 10, 5)
    np.place(detailed_array, np_update == 10, 1)

    # Water bodies
    np.place(detailed_array, np_ua_osm == 50 or np_update == 60, 7)
    np.place(detailed_meta_array, np_ua_osm == 50 or np_update == 60, 1)

    # Urban - Where Urban Atlas IS NOT NULL
    np.place(detailed_array, np_ua_osm == 11, 1)
    np.place(detailed_meta_array, np_ua_osm == 11, 2)

    np.place(detailed_array, np_ua_osm == 12, 2)
    np.place(detailed_meta_array, np_ua_osm == 12, 2)

    np.place(detailed_array, np_ua_osm == 13, 3)
    np.place(detailed_meta_array, np_ua_osm == 13, 2)

    np.place(detailed_array, np_ua_osm == 14, 4)
    np.place(detailed_meta_array, np_ua_osm == 14, 2)

    # Urban Atlas - Class 30 to 6
    np.place(detailed_array, np_ua_osm == 30, 6)
    np.place(detailed_meta_array, np_ua_osm == 30, 2)

    # Create Detailed Globe Cover 30
    obj_to_rst(detailed_array,
               detailed_globe_raster,
               original_globe_raster,
               noData=0)

    # Create Detailed Globe Cover 30 meta
    detailed_meta = os.path.join(
        os.path.dirname(detailed_globe_raster), '{n}_meta{e}'.format(
            n=os.path.splitext(os.path.basename(detailed_meta))[0],
            e=os.path.splitext(os.path.basename(detailed_meta))[1]))
    obj_to_rst(detailed_meta_array,
               detailed_meta,
               original_globe_raster,
               noData=0)
Exemplo n.º 13
0
Arquivo: rst.py Projeto: jasp382/glass
def floatrst_to_intrst(in_rst, out_rst):
    """
    Raster with float data to Raster with Integer Values
    """

    import numpy as np
    from osgeo import gdal
    from glass.g.prop.img import get_nd
    from glass.g.wt.rst import obj_to_rst

    nds = {
        'int8': -128,
        'int16': -32768,
        'int32': -2147483648,
        'uint8': 255,
        'uint16': 65535,
        'uint32': 4294967295
    }

    # Open Raster
    img = gdal.Open(in_rst)

    # Raster to Array
    rstnum = img.ReadAsArray()

    # Round data
    rstint = np.around(rstnum, decimals=0)

    # Get min and max
    tstmin = rstint.min()
    tstmax = rstint.max()

    try:
        nd = int(round(get_nd(img), 0))
    except:
        nd = None

    if tstmin == nd:
        np.place(rstint, rstint == nd, np.nan)
        rstmin = rstint.min()
        rstmax = tstmax
    else:
        rstmin = tstmin

        if tstmax == nd:
            np.place(rstint, rstint == nd, np.nan)
            rstmax = rstint.max()
        else:
            rstmax = tstmax

    # Get dtype for output raster
    if rstmin < 0:
        if rstmin <= -128:
            if rstmin <= -32768:
                tmin = 'int32'
            else:
                tmin = 'int16'
        else:
            tmin = 'int8'
    else:
        tmin = 'u'

    if tmin == 'u':
        if rstmax >= 255:
            if rstmax >= 65535:
                tmax = 'uint32'
            else:
                tmax = 'uint16'
        else:
            tmax = 'uint8'

    else:
        if tmin == 'int8':
            if rstmax >= 127:
                if rstmax >= 32767:
                    tmax = 'int32'
                else:
                    tmax = 'int16'
            else:
                tmax = 'int8'

        elif tmin == 'int16':
            if rstmax >= 32767:
                tmax = 'int32'
            else:
                tmax = 'int16'
        else:
            tmax = 'int32'

    if tmax == 'int8':
        nt = np.int8
    elif tmax == 'int16':
        nt = np.int16
    elif tmax == 'int32':
        nt = np.int32
    elif tmax == 'uint8':
        nt = np.uint8
    elif tmax == 'uint16':
        nt = np.uint16
    else:
        nt = np.uint32

    # Get nodata for new raster
    new_nd = nds[tmax]

    # Place NoData value
    np.nan_to_num(rstint, copy=False, nan=new_nd)

    # Convert array type to integer
    rstint = rstint.astype(nt)

    # Export result to file and return
    return obj_to_rst(rstint, out_rst, img, noData=new_nd)
Exemplo n.º 14
0
Arquivo: rst.py Projeto: jasp382/glass
def conv_rst_dtype(rst, out, odtype):
    """
    Change Raster Dtype

    odtype options:
    * byte
    * int8
    * uint8
    * int16
    * uint16
    * int32
    * uint32
    * float32
    """

    import numpy as np
    from osgeo import gdal
    from glass.g.wt.rst import obj_to_rst

    # Open Raster
    src = gdal.Open(rst, gdal.GA_ReadOnly)
    imgnum = src.ReadAsArray()

    # Get nodata value
    ndval = src.GetRasterBand(1).GetNoDataValue()

    # Get new data type
    if odtype == 'int8':
        dt = np.int8
        ndval = int(ndval)

    elif odtype == 'uint8':
        dt = np.uint8
        ndval = int(ndval)

    elif odtype == 'int16':
        dt = np.int16
        ndval = int(ndval)

    elif odtype == 'uint16':
        dt = np.uint16
        ndval = int(ndval)

    elif odtype == 'int32':
        dt = np.int32
        ndval = int(ndval)

    elif odtype == 'uint32':
        dt = np.uint32
        ndval = int(ndval)

    elif odtype == 'float32':
        dt = np.float32
        ndval = float(ndval)

    elif odtype == 'byte':
        dt = np.byte
        ndval = int(ndval)

    else:
        dt = np.float32
        ndval = float(ndval)

    # Data type conversion
    newnum = imgnum.astype(dt)

    # Export new raster
    obj_to_rst(newnum, out, src, noData=ndval)

    return out
Exemplo n.º 15
0
Arquivo: cls.py Projeto: jasp382/glass
def imgcls_from_mdl(mdl, imgvar, outrst, fileformat='.tif'):
    """
    Classification from Model File
    """

    import os
    from joblib import load
    from osgeo import gdal, gdal_array
    import numpy as np
    from glass.g.wt.rst import obj_to_rst

    if type(imgvar) != list:
        # Check if it is a folder
        if os.path.isdir(imgvar):
            from glass.pys.oss import lst_ff

            imgvar = lst_ff(imgvar,
                            file_format=fileformat if fileformat else '.tif')

        else:
            imgvar = [imgvar]

    # Read model file
    rf = load(mdl)

    # Open feature images
    img_var = [gdal.Open(i, gdal.GA_ReadOnly) for i in imgvar]

    # Get NoData Value
    nd_val = img_var[0].GetRasterBand(1).GetNoDataValue()

    # Get band number of each raster
    img_bnd = [i.RasterCount for i in img_var]

    # Check images shape
    ref_shp = (img_var[0].RasterYSize, img_var[0].RasterXSize)
    if len(img_var) > 1:
        for r in range(1, len(img_var)):
            rst_shp = (img_var[r].RasterYSize, img_var[r].RasterXSize)

            if ref_shp != rst_shp:
                raise ValueError(
                    'There are at least two raster files with different shape')

    # Get features number
    nvar = sum(img_bnd)

    # Convert feature images to array
    X = np.zeros((ref_shp[0], ref_shp[1], nvar),
                 gdal_array.GDALTypeCodeToNumericTypeCode(
                     img_var[0].GetRasterBand(1).DataType))

    f = 0
    for r in range(len(img_var)):
        for b in range(img_bnd[r]):
            X[:, :, f] = img_var[r].GetRasterBand(b + 1).ReadAsArray()

            f += 1

    # Reshape
    nshp = (X.shape[0] * X.shape[1], X.shape[2])
    n_x = X[:, :, :nvar].reshape(nshp)

    # Predict
    y_cls = rf.predict(n_x)

    # Reshape result
    res = y_cls.reshape(X[:, :, 0].shape)

    # Place nodata values
    tmp = img_var[0].GetRasterBand(1).ReadAsArray()
    np.place(res, tmp == nd_val, 255)

    # Export result
    obj_to_rst(res, outrst, imgvar[0], noData=255)

    return outrst
Exemplo n.º 16
0
def num_roads(osmdata, nom, lineTbl, polyTbl, folder, cellsize, srs,
              rstTemplate):
    """
    Select Roads and convert To Raster
    """

    import datetime as dt
    import os
    import numpy as np
    from threading import Thread
    from glass.g.rd.rst import rst_to_array
    from glass.g.tbl.filter import sel_by_attr
    from glass.g.gp.prox.bfing.sql import splite_buffer
    from glass.g.dp.torst import shp_to_rst
    from glass.g.wt.rst import obj_to_rst
    from glass.ng.prop.sql import row_num

    time_a = dt.datetime.now().replace(microsecond=0)
    NR = row_num(osmdata, lineTbl, where="roads IS NOT NULL", api='sqlite')
    time_b = dt.datetime.now().replace(microsecond=0)

    if not NR: return None, {0: ('count_rows_roads', time_b - time_a)}

    timeGasto = {0: ('count_rows_roads', time_b - time_a)}

    # Get Roads Buffer
    LULC_CLS = '1221' if nom != "GLOBE_LAND_30" else '801'
    bfShps = []

    def exportAndBuffer():
        time_cc = dt.datetime.now().replace(microsecond=0)
        roadFile = splite_buffer(osmdata,
                                 lineTbl,
                                 "bf_roads",
                                 "geometry",
                                 os.path.join(folder, 'bf_roads.gml'),
                                 whrClause="roads IS NOT NULL",
                                 outTblIsFile=True,
                                 dissolve=None)
        time_c = dt.datetime.now().replace(microsecond=0)

        distRst = shp_to_rst(roadFile,
                             None,
                             cellsize,
                             -1,
                             os.path.join(folder, 'rst_roads.tif'),
                             epsg=srs,
                             rst_template=rstTemplate,
                             api="gdal")
        time_d = dt.datetime.now().replace(microsecond=0)

        bfShps.append(distRst)

        timeGasto[1] = ('buffer_roads', time_c - time_cc)
        timeGasto[2] = ('to_rst_roads', time_d - time_c)

    BUILDINGS = []

    def exportBuild():
        time_ee = dt.datetime.now().replace(microsecond=0)
        NB = row_num(osmdata,
                     polyTbl,
                     where="building IS NOT NULL",
                     api='sqlite')

        time_e = dt.datetime.now().replace(microsecond=0)

        timeGasto[3] = ('check_builds', time_e - time_ee)

        if not NB:
            return

        bShp = sel_by_attr(
            osmdata,
            "SELECT geometry FROM {} WHERE building IS NOT NULL".format(
                polyTbl),
            os.path.join(folder, 'road_builds.shp'),
            api_gis='ogr')
        time_f = dt.datetime.now().replace(microsecond=0)

        bRst = shp_to_rst(bShp,
                          None,
                          cellsize,
                          -1,
                          os.path.join(folder, 'road_builds.tif'),
                          epsg=srs,
                          rst_template=rstTemplate,
                          api='gdal')
        time_g = dt.datetime.now().replace(microsecond=0)

        BUILDINGS.append(bRst)

        timeGasto[4] = ('export_builds', time_f - time_e)
        timeGasto[5] = ('builds_to_rst', time_g - time_f)

    thrds = [
        Thread(name="build-th", target=exportBuild),
        Thread(name='roads-th', target=exportAndBuffer)
    ]

    for t in thrds:
        t.start()
    for t in thrds:
        t.join()

    if not len(BUILDINGS):
        return {LULC_CLS: bfShps[0]}

    time_x = dt.datetime.now().replace(microsecond=0)
    BUILD_ARRAY = rst_to_array(BUILDINGS[0], with_nodata=True)
    rst_array = rst_to_array(bfShps[0], with_nodata=True)
    np.place(rst_array, BUILD_ARRAY == 1, 0)

    newRaster = obj_to_rst(rst_array,
                           os.path.join(folder, 'fin_roads.tif'),
                           rstTemplate,
                           noData=-1)

    time_z = dt.datetime.now().replace(microsecond=0)

    timeGasto[6] = ('sanitize_roads', time_z - time_x)

    return {int(LULC_CLS): newRaster}, timeGasto
Exemplo n.º 17
0
def gdal_slope(dem, srs, slope, unit='DEGREES'):
    """
    Create Slope Raster
    
    TODO: Test and see if is running correctly
    """
    
    import numpy;         import math
    from osgeo            import gdal
    from scipy.ndimage    import convolve
    from glass.g.rd.rst   import rst_to_array
    from glass.g.wt.rst   import obj_to_rst
    from glass.g.prop.rst import get_cellsize, get_nodata
    
    # ################ #
    # Global Variables #
    # ################ #
    cellsize = get_cellsize(dem, gisApi='gdal')
    # Get Nodata Value
    NoData = get_nodata(dem)
    
    # #################### #
    # Produce Slope Raster #
    # #################### #
    # Get Elevation array
    arr_dem = rst_to_array(dem)
    # We have to get a array with the number of nearst cells with values
    with_data = numpy.zeros((arr_dem.shape[0], arr_dem.shape[1]))
    numpy.place(with_data, arr_dem!=NoData, 1.0)
    mask = numpy.array([[1,1,1],
                        [1,0,1],
                        [1,1,1]])
    arr_neigh = convolve(with_data, mask, mode='constant')
    numpy.place(arr_dem, arr_dem==NoData, 0.0)
    # The rate of change in the x direction for the center cell e is:
    kernel_dz_dx_left = numpy.array([[0,0,1],
                                     [0,0,2],
                                     [0,0,1]])
    kernel_dz_dx_right = numpy.array([[1,0,0],
                                     [2,0,0],
                                     [1,0,0]])
    dz_dx = (convolve(arr_dem, kernel_dz_dx_left, mode='constant')-convolve(arr_dem, kernel_dz_dx_right, mode='constant')) / (arr_neigh * cellsize)
    # The rate of change in the y direction for cell e is:
    kernel_dz_dy_left = numpy.array([[0,0,0],
                                    [0,0,0],
                                    [1,2,1]])
    kernel_dz_dy_right = numpy.array([[1,2,1],
                                    [0,0,0],
                                    [0,0,0]])
    dz_dy = (convolve(arr_dem, kernel_dz_dy_left, mode='constant')-convolve(arr_dem, kernel_dz_dy_right, mode='constant')) / (arr_neigh * cellsize)
    # Taking the rate of change in the x and y direction, the slope for the center cell e is calculated using
    rise_run = ((dz_dx)**2 + (dz_dy)**2)**0.5
    if unit=='DEGREES':
        arr_slope = numpy.arctan(rise_run) * 57.29578
    elif unit =='PERCENT_RISE':
        arr_slope = numpy.tan(numpy.arctan(rise_run)) * 100.0
    # Estimate the slope for the cells with less than 8 neigh
    aux_dem = rst_to_array(dem)
    index_vizinhos = numpy.where(arr_neigh<8)
    for idx in range(len(index_vizinhos[0])):
        # Get Value of the cell
        lnh = index_vizinhos[0][idx]
        col = index_vizinhos[1][idx]
        e = aux_dem[lnh][col]
        a = aux_dem[lnh-1][col-1]
        if a == NoData:
            a = e
        if lnh==0 or col==0:
            a=e
        b = aux_dem[lnh-1][col]
        if b == NoData:
            b = e
        if lnh==0:
            b=e
        try:
            c = aux_dem[lnh-1][col+1]
            if c == NoData:
                c=e
            if lnh==0:
                c=e
        except:
            c = e
        d = aux_dem[lnh][col-1]
        if d == NoData:
            d = e
        if col==0:
            d=e
        try:
            f = aux_dem[lnh][col+1]
            if f == NoData:
                f=e
        except:
            f=e
        try:
            g = aux_dem[lnh+1][col-1]
            if g == NoData:
                g=e
            if col==0:
                g=e
        except:
            g=e
        try:
            h = aux_dem[lnh+1][col]
            if h ==NoData:
                h = e
        except:
            h=e
        try:
            i = aux_dem[lnh+1][col+1]
            if i == NoData:
                i = e
        except:
            i=e
        dz_dx = ((c + 2*f + i) - (a + 2*d + g)) / (8 * cellsize)
        dz_dy = ((g + 2*h + i) - (a + 2*b + c)) / (8 * cellsize)
        rise_sun = ((dz_dx)**2 + (dz_dy)**2)**0.5
        if unit == 'DEGREES':
            arr_slope[lnh][col] = math.atan(rise_sun) * 57.29578
        elif unit == 'PERCENT_RISE':
            arr_slope[lnh][col] = math.tan(math.atan(rise_sun)) * 100.0
    # Del value originally nodata
    numpy.place(arr_slope, aux_dem==NoData, numpy.nan)
    #arr_slope[lnh][col] = slope_degres
    obj_to_rst(arr_slope, slope, dem)
Exemplo n.º 18
0
def rcls_rst(inrst, rclsRules, outrst, api='gdal', maintain_ext=True):
    """
    Reclassify a raster (categorical and floating points)
    
    if api == 'gdal
    rclsRules = {
        1 : 99,
        2 : 100
        ...
    }
    
    or
    
    rclsRules = {
        (0, 8) : 1
        (8, 16) : 2
        '*'     : 'NoData'
    }
    
    elif api == grass:
    rclsRules should be a path to a text file
    """

    if api == 'gdal':
        import numpy as np
        import os
        from osgeo import gdal
        from glass.g.wt.rst import obj_to_rst
        from glass.g.rd.rsrc import imgsrc_to_num
        from glass.g.prop.img import get_nd

        if not os.path.exists(inrst):
            raise ValueError('File {} does not exist!'.format(inrst))

        # Open Raster
        img = gdal.Open(inrst)

        # Raster to Array
        rst_num = imgsrc_to_num(img)

        nodataVal = get_nd(img)

        rcls_num = np.full(rst_num.shape, 255, dtype=np.uint8)

        # Change values
        for k in rclsRules:
            if rclsRules[k] == 'NoData':
                continue

            if type(k) == str:
                continue

            elif type(k) == tuple:
                q = (rst_num > k[0]) & (rst_num <= k[1])

            else:
                q = rst_num == k

            np.place(rcls_num, q, rclsRules[k])

        if '*' in rclsRules and rclsRules['*'] != 'NoData':
            np.place(rcls_num, rcls_num == 255, rclsRules['*'])

        if 'NoData' in rclsRules and rclsRules['NoData'] != 'NoData':
            np.place(rcls_num, rst_num == nodataVal, rclsRules['NoData'])

        if not maintain_ext:
            from glass.g.rst.rshp import rshp_to_data

            left, cellx, z, top, c, celly = img.GetGeoTransform()

            clip_rcls, n_left, n_top = rshp_to_data(rcls_num, 255, left, cellx,
                                                    top, celly)

            return obj_to_rst(clip_rcls,
                              outrst,
                              img,
                              noData=255,
                              geotrans=(n_left, cellx, z, n_top, c, celly))
        else:
            return obj_to_rst(rcls_num, outrst, img, noData=255)

    elif api == "pygrass":
        from grass.pygrass.modules import Module

        r = Module('r.reclass',
                   input=inrst,
                   output=outrst,
                   rules=rclsRules,
                   overwrite=True,
                   run_=False,
                   quiet=True)

        r()

    else:
        raise ValueError(f"API {api} is not available")

    return outrst
Exemplo n.º 19
0
def proprndcells_to_rst(inrst,
                        class_proportion,
                        out_rst,
                        sample_dim,
                        cls_sample_min=None):
    """
    Extract some cells from one raster and save them into a new raster

    The cells are extracted in a random way for each class in inrst.
    The number of cells extracted for each class are based on the values
    in class_proportion object
    """

    from osgeo import gdal, gdal_array
    import numpy as np
    from glass.g.wt.rst import obj_to_rst

    img = gdal.Open(inrst, gdal.GA_ReadOnly)

    nd_val = img.GetRasterBand(1).GetNoDataValue()

    # Image to array
    num_ref = img.GetRasterBand(1).ReadAsArray()

    # Reshape array
    oned_ref = num_ref.reshape(num_ref.shape[0] * num_ref.shape[1])

    # Get classes in inrst array
    id_cls = list(np.unique(oned_ref))

    # Remove nodata value from id_cls
    if nd_val in id_cls:
        id_cls.remove(nd_val)

    # All classes in class_proportion must be in id_cls
    ks = list(class_proportion.keys())
    for k in ks:
        if k not in id_cls:
            del class_proportion[k]

    # Exclude values not in ks
    ks = list(class_proportion.keys())
    __id_cls = id_cls.copy()
    for c in __id_cls:
        if c not in ks:
            id_cls.remove(c)

    # Get absolute frequencies of inrst
    # Exclude no data values
    ref_sem_nd = oned_ref[oned_ref != nd_val]
    freq = np.bincount(ref_sem_nd)
    freq = freq[freq != 0]

    # Get number of cells for each class based on class_proportions
    class_cells = {
        c: int(round(class_proportion[c] * sample_dim / 100, 0))
        for c in class_proportion
    }

    # The n_cells for each class could not be lesser than
    # cls_sample_min
    for c in class_cells:
        if cls_sample_min:
            if class_cells[c] < cls_sample_min:
                class_cells[c] = cls_sample_min

        # n_cells for each class could not be larger than the class frequency
        for e in range(len(id_cls)):
            if id_cls[e] == c:
                if freq[e] < class_cells[c]:
                    class_cells[c] = freq[e]

                break

    # Get index array
    idx_ref = np.arange(oned_ref.size)

    # Get indexes for cells of each class
    idx_cls = [idx_ref[oned_ref == c] for c in id_cls]

    # Get indexes to be selected for each class
    sel_cls = [
        np.random.choice(idx_cls[e],
                         size=class_cells[id_cls[e]],
                         replace=False) for e in range(len(id_cls))
    ]

    # Create result
    res = np.zeros(oned_ref.shape, dtype=oned_ref.dtype)

    # Place selected cells in result array
    for c in range(len(id_cls)):
        res[sel_cls[c]] = id_cls[c]

    # Place nodata
    np.place(res, oned_ref == nd_val, nd_val)
    np.place(res, res == 0, nd_val)

    # Reshape
    res = res.reshape(num_ref.shape)

    # Save result
    obj_to_rst(res, out_rst, img, noData=nd_val)

    return out_rst
Exemplo n.º 20
0
def lnd8_dn_to_ref(folder, img_format, meta_json, outWorkspace, srs):
    """
    Landsat8 digital numbers to surface reflectance
    """

    import math
    import json
    import os
    from glass.pys.oss import lst_ff
    from glass.g.rd.rst import rst_to_array
    from glass.g.prop.rst import get_cellsize, rst_stats
    from glass.g.wt.rst import obj_to_rst

    def Get_RTA(Ml, Qcalc, Al):
        """
        Obtem Radiancia no Topo da Atmosfera
        
        Ml - relacao da radiancia multibanda
        Qcalc - imagem de satelite original
        Al - radiancia add band
        """

        Llambda = Ml * Qcalc + Al

        return Llambda

    def GetIrraSolar(d, Lmax, Pmax):
        """
        d - distancia da terra ao sol (com base no dia do ano em
        que a imagem foi recolhida)
        ESUN - irradiancia solar media exoatmosferica
        Lmax - radiancia maxima
        Pmax - reflectancia maxima
        """
        return (math.pi * d**2) * (Lmax / Pmax)

    def GetRefAparente(d, esun, rta, Z):
        """
        Reflectancia aparente
        Z - angulo zenital do sol
        """
        pp = math.pi * rta * d**2 / esun * math.cos(Z)
        return pp

    def GetRefSuperfice(DNmin, Ml, Al, IrrSolar, Z, d, RefAparente):
        """Reflectancia a superficie"""
        Lp = (Ml * DNmin + Al - 0.01 * IrrSolar) * (math.cos(Z) / math.pi *
                                                    d**2)
        p = math.pi * (RefAparente - Lp) * d**2 / IrrSolar * math.cos(Z)
        return p

    lst_bands = lst_ff(folder, file_format=img_format)
    json_file = open(meta_json, 'r')
    json_data = json.load(json_file)
    cellsize = get_cellsize(lst_bands[0], gisApi='gdal')

    # Estimate Surface Reflectance for each band
    for bnd in lst_bands:
        # Convert images to numpy array
        img = rst_to_array(bnd)
        # Calculations of each pixel; store results on a new numpy array
        rta_array = Get_RTA(
            json_data[u"RADIANCE_MULT_BAND"][os.path.basename(bnd)], img,
            json_data[u"RADIANCE_ADD_BAND"][os.path.basename(bnd)])
        solar_irradiation = GetIrraSolar(
            json_data[u"EARTH_SUN_DISTANCE"],
            json_data[u"RADIANCE_MAXIMUM_BAND"][os.path.basename(bnd)],
            json_data[u"REFLECTANCE_MAXIMUM_BAND"][os.path.basename(bnd)])
        ref_aparente_array = GetRefAparente(json_data[u"EARTH_SUN_DISTANCE"],
                                            solar_irradiation, rta_array,
                                            90 - json_data[u"SUN_ELEVATION"])
        new_map = GetRefSuperfice(
            rst_stats(bnd, api='gdal')['MIN'],
            json_data[u"RADIANCE_MULT_BAND"][os.path.basename(bnd)],
            json_data[u"RADIANCE_ADD_BAND"][os.path.basename(bnd)],
            solar_irradiation, 90 - json_data[u"SUN_ELEVATION"],
            json_data[u"EARTH_SUN_DISTANCE"], ref_aparente_array)
        obj_to_rst(new_map, os.path.join(outWorkspace, os.path.basename(bnd)),
                   bnd)
Exemplo n.º 21
0
Arquivo: num.py Projeto: jasp382/glass
def osm2lulc(osmdata,
             nomenclature,
             refRaster,
             lulcRst,
             overwrite=None,
             dataStore=None,
             roadsAPI='POSTGIS'):
    """
    Convert OSM data into Land Use/Land Cover Information
    
    A matrix based approach
    
    roadsAPI Options:
    * SQLITE
    * POSTGIS
    """

    # ************************************************************************ #
    # Python Modules from Reference Packages #
    # ************************************************************************ #
    import os
    import numpy
    import datetime
    from threading import Thread
    from osgeo import gdal
    # ************************************************************************ #
    # Dependencies #
    # ************************************************************************ #
    from glass.g.rd.rst import rst_to_array
    from glass.g.prop import check_isRaster
    from glass.g.prop.rst import get_cellsize
    from glass.pys.oss import mkdir, copy_file
    from glass.pys.oss import fprop
    if roadsAPI == 'POSTGIS':
        from glass.ng.sql.db import create_db
        from glass.g.it.db import osm_to_psql
        from glass.ete.osm2lulc.mod2 import pg_num_roads
        from glass.ng.sql.bkup import dump_db
        from glass.ng.sql.db import drop_db
    else:
        from glass.g.it.osm import osm_to_sqdb
        from glass.ete.osm2lulc.mod2 import num_roads
    from glass.ete.osm2lulc.utils import osm_project, add_lulc_to_osmfeat
    from glass.ete.osm2lulc.utils import osmlulc_rsttbl
    from glass.ete.osm2lulc.utils import get_ref_raster
    from glass.ete.osm2lulc.mod1 import num_selection
    from glass.ete.osm2lulc.m3_4 import num_selbyarea
    from glass.ete.osm2lulc.mod5 import num_base_buffer
    from glass.ete.osm2lulc.mod6 import num_assign_builds
    from glass.g.wt.rst import obj_to_rst
    # ************************************************************************ #
    # Global Settings #
    # ************************************************************************ #
    # Check if input parameters exists!
    if not os.path.exists(os.path.dirname(lulcRst)):
        raise ValueError('{} does not exist!'.format(os.path.dirname(lulcRst)))

    if not os.path.exists(osmdata):
        raise ValueError(
            'File with OSM DATA ({}) does not exist!'.format(osmdata))

    if not os.path.exists(refRaster):
        raise ValueError(
            'File with reference area ({}) does not exist!'.format(refRaster))

    # Check if Nomenclature is valid
    nomenclature = "URBAN_ATLAS" if nomenclature != "URBAN_ATLAS" and \
        nomenclature != "CORINE_LAND_COVER" and \
        nomenclature == "GLOBE_LAND_30" else nomenclature

    time_a = datetime.datetime.now().replace(microsecond=0)

    workspace = os.path.join(os.path.dirname(lulcRst),
                             'num_osmto') if not dataStore else dataStore

    # Check if workspace exists:
    if os.path.exists(workspace):
        if overwrite:
            mkdir(workspace, overwrite=True)
        else:
            raise ValueError('Path {} already exists'.format(workspace))
    else:
        mkdir(workspace, overwrite=None)

    # Get Ref Raster and EPSG
    refRaster, epsg = get_ref_raster(refRaster, workspace, cellsize=2)
    CELLSIZE = get_cellsize(refRaster, gisApi='gdal')

    from glass.ete.osm2lulc import osmTableData, PRIORITIES

    time_b = datetime.datetime.now().replace(microsecond=0)
    # ************************************************************************ #
    # Convert OSM file to SQLITE DB or to POSTGIS DB #
    # ************************************************************************ #
    if roadsAPI == 'POSTGIS':
        osm_db = create_db(fprop(osmdata, 'fn', forceLower=True),
                           overwrite=True)
        osm_db = osm_to_psql(osmdata, osm_db)

    else:
        osm_db = osm_to_sqdb(osmdata, os.path.join(workspace, 'osm.sqlite'))
    time_c = datetime.datetime.now().replace(microsecond=0)
    # ************************************************************************ #
    # Add Lulc Classes to OSM_FEATURES by rule #
    # ************************************************************************ #
    add_lulc_to_osmfeat(osm_db, osmTableData, nomenclature, api=roadsAPI)
    time_d = datetime.datetime.now().replace(microsecond=0)
    # ************************************************************************ #
    # Transform SRS of OSM Data #
    # ************************************************************************ #
    osmTableData = osm_project(
        osm_db,
        epsg,
        api=roadsAPI,
        isGlobeLand=None if nomenclature != "GLOBE_LAND_30" else True)
    time_e = datetime.datetime.now().replace(microsecond=0)
    # ************************************************************************ #
    # MapResults #
    # ************************************************************************ #
    mergeOut = {}
    timeCheck = {}
    RULES = [1, 2, 3, 4, 5, 7]

    def run_rule(ruleID):
        time_start = datetime.datetime.now().replace(microsecond=0)
        _osmdb = copy_file(
            osm_db,
            os.path.splitext(osm_db)[0] +
            '_r{}.sqlite'.format(ruleID)) if roadsAPI == 'SQLITE' else None
        # ******************************************************************** #
        # 1 - Selection Rule #
        # ******************************************************************** #
        if ruleID == 1:
            res, tm = num_selection(_osmdb if _osmdb else osm_db,
                                    osmTableData['polygons'],
                                    workspace,
                                    CELLSIZE,
                                    epsg,
                                    refRaster,
                                    api=roadsAPI)
        # ******************************************************************** #
        # 2 - Get Information About Roads Location #
        # ******************************************************************** #
        elif ruleID == 2:
            res, tm = num_roads(
                _osmdb, nomenclature, osmTableData['lines'],
                osmTableData['polygons'], workspace, CELLSIZE, epsg,
                refRaster) if _osmdb else pg_num_roads(
                    osm_db, nomenclature, osmTableData['lines'],
                    osmTableData['polygons'], workspace, CELLSIZE, epsg,
                    refRaster)

        # ******************************************************************** #
        # 3 - Area Upper than #
        # ******************************************************************** #
        elif ruleID == 3:
            if nomenclature != "GLOBE_LAND_30":
                res, tm = num_selbyarea(osm_db if not _osmdb else _osmdb,
                                        osmTableData['polygons'],
                                        workspace,
                                        CELLSIZE,
                                        epsg,
                                        refRaster,
                                        UPPER=True,
                                        api=roadsAPI)
            else:
                return

        # ******************************************************************** #
        # 4 - Area Lower than #
        # ******************************************************************** #
        elif ruleID == 4:
            if nomenclature != "GLOBE_LAND_30":
                res, tm = num_selbyarea(osm_db if not _osmdb else _osmdb,
                                        osmTableData['polygons'],
                                        workspace,
                                        CELLSIZE,
                                        epsg,
                                        refRaster,
                                        UPPER=False,
                                        api=roadsAPI)
            else:
                return

        # ******************************************************************** #
        # 5 - Get data from lines table (railway | waterway) #
        # ******************************************************************** #
        elif ruleID == 5:
            res, tm = num_base_buffer(osm_db if not _osmdb else _osmdb,
                                      osmTableData['lines'],
                                      workspace,
                                      CELLSIZE,
                                      epsg,
                                      refRaster,
                                      api=roadsAPI)
        # ******************************************************************** #
        # 7 - Assign untagged Buildings to tags #
        # ******************************************************************** #
        elif ruleID == 7:
            if nomenclature != "GLOBE_LAND_30":
                res, tm = num_assign_builds(osm_db if not _osmdb else _osmdb,
                                            osmTableData['points'],
                                            osmTableData['polygons'],
                                            workspace,
                                            CELLSIZE,
                                            epsg,
                                            refRaster,
                                            apidb=roadsAPI)

            else:
                return

        time_end = datetime.datetime.now().replace(microsecond=0)
        mergeOut[ruleID] = res
        timeCheck[ruleID] = {'total': time_end - time_start, 'detailed': tm}

    thrds = []
    for r in RULES:
        thrds.append(
            Thread(name="to_{}".format(str(r)), target=run_rule, args=(r, )))

    for t in thrds:
        t.start()
    for t in thrds:
        t.join()

    # Merge all results into one Raster
    compileResults = {}
    for rule in mergeOut:
        for cls in mergeOut[rule]:
            if cls not in compileResults:
                if type(mergeOut[rule][cls]) == list:
                    compileResults[cls] = mergeOut[rule][cls]
                else:
                    compileResults[cls] = [mergeOut[rule][cls]]

            else:
                if type(mergeOut[rule][cls]) == list:
                    compileResults[cls] += mergeOut[rule][cls]
                else:
                    compileResults[cls].append(mergeOut[rule][cls])

    time_m = datetime.datetime.now().replace(microsecond=0)
    # All Rasters to Array
    arrayRst = {}
    for cls in compileResults:
        for raster in compileResults[cls]:
            if not raster:
                continue

            array = rst_to_array(raster)

            if cls not in arrayRst:
                arrayRst[cls] = [array.astype(numpy.uint8)]

            else:
                arrayRst[cls].append(array.astype(numpy.uint8))
    time_n = datetime.datetime.now().replace(microsecond=0)

    # Sum Rasters of each class
    for cls in arrayRst:
        if len(arrayRst[cls]) == 1:
            sumArray = arrayRst[cls][0]

        else:
            sumArray = arrayRst[cls][0]

            for i in range(1, len(arrayRst[cls])):
                sumArray = sumArray + arrayRst[cls][i]

        arrayRst[cls] = sumArray

    time_o = datetime.datetime.now().replace(microsecond=0)

    # Apply priority rule
    __priorities = PRIORITIES[nomenclature + "_NUMPY"]

    for lulcCls in __priorities:
        __lulcCls = rstcls_map(lulcCls)

        if __lulcCls not in arrayRst:
            continue
        else:
            numpy.place(arrayRst[__lulcCls], arrayRst[__lulcCls] > 0, lulcCls)

    for i in range(len(__priorities)):
        lulc_i = rstcls_map(__priorities[i])

        if lulc_i not in arrayRst:
            continue

        else:
            for e in range(i + 1, len(__priorities)):
                lulc_e = rstcls_map(__priorities[e])

                if lulc_e not in arrayRst:
                    continue

                else:
                    numpy.place(arrayRst[lulc_e],
                                arrayRst[lulc_i] == __priorities[i], 0)

    time_p = datetime.datetime.now().replace(microsecond=0)

    # Merge all rasters
    startCls = 'None'
    for i in range(len(__priorities)):
        lulc_i = rstcls_map(__priorities[i])

        if lulc_i in arrayRst:
            resultSum = arrayRst[lulc_i]
            startCls = i
            break

    if startCls == 'None':
        return 'NoResults'

    for i in range(startCls + 1, len(__priorities)):
        lulc_i = rstcls_map(__priorities[i])

        if lulc_i not in arrayRst:
            continue

        resultSum = resultSum + arrayRst[lulc_i]

    # Save Result
    outIsRst = check_isRaster(lulcRst)
    if not outIsRst:
        from glass.pys.oss import fprop

        lulcRst = os.path.join(os.path.dirname(lulcRst),
                               fprop(lulcRst, 'fn') + '.tif')

    numpy.place(resultSum, resultSum == 0, 1)
    obj_to_rst(resultSum, lulcRst, refRaster, noData=1)

    osmlulc_rsttbl(
        nomenclature + "_NUMPY",
        os.path.join(os.path.dirname(lulcRst),
                     os.path.basename(lulcRst) + '.vat.dbf'))

    time_q = datetime.datetime.now().replace(microsecond=0)

    # Dump Database if PostGIS was used
    # Drop Database if PostGIS was used
    if roadsAPI == 'POSTGIS':
        dump_db(osm_db, os.path.join(workspace, osm_db + '.sql'), api='psql')
        drop_db(osm_db)

    return lulcRst, {
        0: ('set_settings', time_b - time_a),
        1: ('osm_to_sqdb', time_c - time_b),
        2: ('cls_in_sqdb', time_d - time_c),
        3: ('proj_data', time_e - time_d),
        4: ('rule_1', timeCheck[1]['total'], timeCheck[1]['detailed']),
        5: ('rule_2', timeCheck[2]['total'], timeCheck[2]['detailed']),
        6:
        None if 3 not in timeCheck else
        ('rule_3', timeCheck[3]['total'], timeCheck[3]['detailed']),
        7:
        None if 4 not in timeCheck else
        ('rule_4', timeCheck[4]['total'], timeCheck[4]['detailed']),
        8: ('rule_5', timeCheck[5]['total'], timeCheck[5]['detailed']),
        9:
        None if 7 not in timeCheck else
        ('rule_7', timeCheck[7]['total'], timeCheck[7]['detailed']),
        10: ('rst_to_array', time_n - time_m),
        11: ('sum_cls', time_o - time_n),
        12: ('priority_rule', time_p - time_o),
        13: ('merge_rst', time_q - time_p)
    }